diff --git a/.github/release.yml b/.github/release.yml index a27541985e3d8..ea43f8b3f752f 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -4,6 +4,7 @@ changelog: labels: - internal - documentation + - formatter categories: - title: Breaking Changes labels: diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 0ab1fc9cd4796..b891e1d4fd5fe 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -3,12 +3,12 @@ name: Benchmark on: pull_request: paths: - - 'Cargo.toml' - - 'Cargo.lock' - - 'rust-toolchain' - - 'crates/**' - - '!crates/ruff_dev' - - '!crates/ruff_shrinking' + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain" + - "crates/**" + - "!crates/ruff_dev" + - "!crates/ruff_shrinking" workflow_dispatch: @@ -22,7 +22,7 @@ jobs: name: "Run | ${{ matrix.os }}" strategy: matrix: - os: [ ubuntu-latest, windows-latest ] + os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 487de99d85080..b2681cec59f80 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [ main ] + branches: [main] pull_request: workflow_dispatch: @@ -16,7 +16,7 @@ env: CARGO_TERM_COLOR: always RUSTUP_MAX_RETRIES: 10 PACKAGE_NAME: ruff - PYTHON_VERSION: "3.11" # to build abi3 wheels + PYTHON_VERSION: "3.11" jobs: determine_changes: @@ -42,6 +42,7 @@ jobs: - "!crates/ruff_formatter/**" - "!crates/ruff_dev/**" - "!crates/ruff_shrinking/**" + - scripts/* formatter: - Cargo.toml @@ -54,7 +55,8 @@ jobs: - crates/ruff_python_index/** - crates/ruff_text_size/** - crates/ruff_python_parser/** - + - crates/ruff_dev/** + - scripts/* cargo-fmt: name: "cargo fmt" @@ -83,7 +85,7 @@ jobs: cargo-test: strategy: matrix: - os: [ ubuntu-latest, windows-latest ] + os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} name: "cargo test | ${{ matrix.os }}" steps: @@ -235,7 +237,6 @@ jobs: - name: "Run cargo-udeps" run: cargo +nightly-2023-06-08 udeps - python-package: name: "python package" runs-on: ubuntu-latest @@ -327,7 +328,7 @@ jobs: name: "Formatter ecosystem and progress checks" runs-on: ubuntu-latest needs: determine_changes - if: needs.determine_changes.outputs.formatter == 'true' + if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: "Install Rust toolchain" @@ -337,9 +338,6 @@ jobs: - name: "Formatter progress" run: scripts/formatter_ecosystem_checks.sh - name: "Github step summary" - run: grep "similarity index" target/progress_projects_report.txt | sort > $GITHUB_STEP_SUMMARY - # CPython is not black formatted, so we run only the stability check - - name: "Clone CPython 3.10" - run: git clone --branch 3.10 --depth 1 https://github.com/python/cpython.git crates/ruff/resources/test/cpython - - name: "Check CPython stability" - run: cargo run --bin ruff_dev -- format-dev --stability-check crates/ruff/resources/test/cpython + run: cat target/progress_projects_stats.txt > $GITHUB_STEP_SUMMARY + - name: "Remove checkouts from cache" + run: rm -r target/progress_projects diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index f5ed1a6e31fae..e340f0aa5a4d4 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -3,7 +3,7 @@ name: mkdocs on: workflow_dispatch: release: - types: [ published ] + types: [published] jobs: mkdocs: @@ -40,7 +40,7 @@ jobs: run: mkdocs build --strict -f mkdocs.generated.yml - name: "Deploy to Cloudflare Pages" if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} - uses: cloudflare/wrangler-action@2.0.0 + uses: cloudflare/wrangler-action@v3.1.0 with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} diff --git a/.github/workflows/flake8-to-ruff.yaml b/.github/workflows/flake8-to-ruff.yaml index 44e41b7d29fe0..8bd34be65cfac 100644 --- a/.github/workflows/flake8-to-ruff.yaml +++ b/.github/workflows/flake8-to-ruff.yaml @@ -66,7 +66,7 @@ jobs: runs-on: windows-latest strategy: matrix: - target: [ x64, x86 ] + target: [x64, x86] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 @@ -94,7 +94,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [ x86_64, i686 ] + target: [x86_64, i686] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 @@ -121,7 +121,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [ aarch64, armv7, s390x, ppc64le, ppc64 ] + target: [aarch64, armv7, s390x, ppc64le, ppc64] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 diff --git a/.github/workflows/playground.yaml b/.github/workflows/playground.yaml index dcb582815ea7a..1c1e2ec857154 100644 --- a/.github/workflows/playground.yaml +++ b/.github/workflows/playground.yaml @@ -3,7 +3,7 @@ name: "[Playground] Release" on: workflow_dispatch: release: - types: [ published ] + types: [published] env: CARGO_INCREMENTAL: 0 @@ -40,7 +40,7 @@ jobs: working-directory: playground - name: "Deploy to Cloudflare Pages" if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} - uses: cloudflare/wrangler-action@2.0.0 + uses: cloudflare/wrangler-action@v3.1.0 with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml index 72b9beaf86df1..cd2070f2fcf85 100644 --- a/.github/workflows/pr-comment.yaml +++ b/.github/workflows/pr-comment.yaml @@ -2,8 +2,8 @@ name: PR Check Comment on: workflow_run: - workflows: [ CI, Benchmark ] - types: [ completed ] + workflows: [CI, Benchmark] + types: [completed] workflow_dispatch: inputs: workflow_run_id: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe81f561de55e..b5d0b2d9a87d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,13 +42,13 @@ repos: name: cargo fmt entry: cargo fmt -- language: system - types: [ rust ] + types: [rust] pass_filenames: false # This makes it a lot faster - id: ruff name: ruff entry: cargo run --bin ruff -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix language: system - types_or: [ python, pyi ] + types_or: [python, pyi] require_serial: true exclude: | (?x)^( @@ -62,5 +62,12 @@ repos: hooks: - id: black + # Prettier + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.0.0 + hooks: + - id: prettier + types: [yaml] + ci: - skip: [ cargo-fmt, dev-generate-all ] + skip: [cargo-fmt, dev-generate-all] diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index f8c7b7913be68..c10e07250f923 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,5 +1,15 @@ # Breaking Changes +## 0.0.283 / 0.284 + +### The target Python version now defaults to 3.8 instead of 3.10 ([#6397](https://github.com/astral-sh/ruff/pull/6397)) + +Previously, when a target Python version was not specified, Ruff would use a default of Python 3.10. However, it is safer to default to an _older_ Python version to avoid assuming the availability of new features. We now default to the oldest supported Python version which is currently Python 3.8. + +(We still support Python 3.7 but since [it has reached EOL](https://devguide.python.org/versions/#unsupported-versions) we've decided not to make it the default here.) + +Note this change was announced in 0.0.283 but not active until 0.0.284. + ## 0.0.277 ### `.ipynb_checkpoints`, `.pyenv`, `.pytest_cache`, and `.vscode` are now excluded by default ([#5513](https://github.com/astral-sh/ruff/pull/5513)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a2942f9733946..6250515efda20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,6 +69,13 @@ and pre-commit to run some validation checks: pipx install pre-commit # or `pip install pre-commit` if you have a virtualenv ``` +You can optionally install pre-commit hooks to automatically run the validation checks +when making a commit: + +```shell +pre-commit install +``` + ### Development After cloning the repository, run Ruff locally from the repository root with: @@ -124,7 +131,6 @@ At time of writing, the repository includes the following crates: - `crates/ruff_macros`: proc macro crate containing macros used by Ruff. - `crates/ruff_python_ast`: library crate containing Python-specific AST types and utilities. - `crates/ruff_python_codegen`: library crate containing utilities for generating Python source code. -- `crates/ruff_python_codegen`: library crate containing utilities for generating Python source code. - `crates/ruff_python_formatter`: library crate implementing the Python formatter. Emits an intermediate representation for each node, which `ruff_formatter` prints based on the configured line length. @@ -565,7 +571,7 @@ An alternative is to convert the perf data to `flamegraph.svg` using [flamegraph](https://github.com/flamegraph-rs/flamegraph) (`cargo install flamegraph`): ```shell -flamegraph --perfdata perf.data +flamegraph --perfdata perf.data --no-inline ``` #### Mac diff --git a/Cargo.lock b/Cargo.lock index 622032c09a222..261438324222e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -800,7 +812,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flake8-to-ruff" -version = "0.0.282" +version = "0.0.286" dependencies = [ "anyhow", "clap", @@ -864,8 +876,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -991,6 +1005,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "imara-diff" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8" +dependencies = [ + "ahash", + "hashbrown 0.12.3", +] + [[package]] name = "imperative" version = "1.0.4" @@ -2042,7 +2066,7 @@ dependencies = [ [[package]] name = "ruff" -version = "0.0.282" +version = "0.0.286" dependencies = [ "annotate-snippets 0.9.1", "anyhow", @@ -2106,6 +2130,7 @@ dependencies = [ "typed-arena", "unicode-width", "unicode_names2", + "uuid", "wsl", ] @@ -2119,6 +2144,7 @@ dependencies = [ "ruff", "ruff_python_ast", "ruff_python_formatter", + "ruff_python_index", "ruff_python_parser", "serde", "serde_json", @@ -2141,7 +2167,7 @@ dependencies = [ [[package]] name = "ruff_cli" -version = "0.0.282" +version = "0.0.286" dependencies = [ "annotate-snippets 0.9.1", "anyhow", @@ -2197,6 +2223,7 @@ dependencies = [ "anyhow", "clap", "ignore", + "imara-diff", "indicatif", "indoc", "itertools", @@ -2316,6 +2343,7 @@ dependencies = [ "insta", "is-macro", "itertools", + "memchr", "once_cell", "ruff_formatter", "ruff_python_ast", @@ -2330,6 +2358,7 @@ dependencies = [ "similar", "smallvec", "thiserror", + "unicode-width", ] [[package]] @@ -2353,7 +2382,6 @@ dependencies = [ "is-macro", "itertools", "lexical-parse-float", - "num-bigint", "num-traits", "rand", "unic-ucd-category", @@ -2375,6 +2403,7 @@ dependencies = [ "ruff_text_size", "rustc-hash", "static_assertions", + "test-case", "tiny-keccak", "unic-emoji-char", "unic-ucd-ident", @@ -2400,6 +2429,7 @@ dependencies = [ "num-traits", "ruff_index", "ruff_python_ast", + "ruff_python_parser", "ruff_python_stdlib", "ruff_source_file", "ruff_text_size", @@ -3319,9 +3349,26 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.0" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", + "rand", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "f7e1ba1f333bd65ce3c9f27de592fcbc256dafe3af2717f56d7c87761fbaccf4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.23", +] [[package]] name = "valuable" diff --git a/Cargo.toml b/Cargo.toml index a5314de6ba9ec..ae97f5676fa1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] edition = "2021" -rust-version = "1.70" +rust-version = "1.71" homepage = "https://beta.ruff.rs/docs" documentation = "https://beta.ruff.rs/docs" repository = "https://github.com/astral-sh/ruff" @@ -49,6 +49,8 @@ toml = { version = "0.7.2" } tracing = "0.1.37" tracing-indicatif = "0.3.4" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } +unicode-width = "0.1.10" +uuid = { version = "1.4.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] } wsl = { version = "0.1.0" } # v1.0.1 diff --git a/README.md b/README.md index 67ac480f6a8e1..9e3fe2029e5d4 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ An extremely fast Python linter, written in Rust. - 🤝 Python 3.11 compatibility - 📦 Built-in caching, to avoid re-analyzing unchanged files - 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports) -- 📏 Over [500 built-in rules](https://beta.ruff.rs/docs/rules/) +- 📏 Over [600 built-in rules](https://beta.ruff.rs/docs/rules/) - ⚖️ [Near-parity](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set - 🔌 Native re-implementations of dozens of Flake8 plugins, like flake8-bugbear @@ -140,7 +140,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook: ```yaml - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.282 + rev: v0.0.286 hooks: - id: ruff ``` @@ -211,8 +211,8 @@ line-length = 88 # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -# Assume Python 3.10. -target-version = "py310" +# Assume Python 3.8 +target-version = "py38" [tool.ruff.mccabe] # Unlike Flake8, default to a complexity level of 10. @@ -233,7 +233,7 @@ linting command. -**Ruff supports over 500 lint rules**, many of which are inspired by popular tools like Flake8, +**Ruff supports over 600 lint rules**, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature. diff --git a/crates/flake8_to_ruff/Cargo.toml b/crates/flake8_to_ruff/Cargo.toml index 662ee703e49ac..69e40f1e06e11 100644 --- a/crates/flake8_to_ruff/Cargo.toml +++ b/crates/flake8_to_ruff/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flake8-to-ruff" -version = "0.0.282" +version = "0.0.286" description = """ Convert Flake8 configuration files to Ruff configuration files. """ diff --git a/crates/ruff/Cargo.toml b/crates/ruff/Cargo.toml index fe8fa3e225128..b873f736fa508 100644 --- a/crates/ruff/Cargo.toml +++ b/crates/ruff/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruff" -version = "0.0.282" +version = "0.0.286" publish = false authors = { workspace = true } edition = { workspace = true } @@ -62,8 +62,6 @@ quick-junit = { version = "0.3.2" } regex = { workspace = true } result-like = { version = "0.4.6" } rustc-hash = { workspace = true } - - schemars = { workspace = true, optional = true } semver = { version = "1.0.16" } serde = { workspace = true } @@ -77,8 +75,9 @@ strum_macros = { workspace = true } thiserror = { version = "1.0.43" } toml = { workspace = true } typed-arena = { version = "2.0.2" } -unicode-width = { version = "0.1.10" } +unicode-width = { workspace = true } unicode_names2 = { version = "0.6.0", git = "https://github.com/youknowone/unicode_names2.git", rev = "4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde" } +uuid = { workspace = true, features = ["v4", "fast-rng", "macro-diagnostics", "js"] } wsl = { version = "0.1.0" } [dev-dependencies] diff --git a/crates/ruff/resources/test/fixtures/eradicate/ERA001.py b/crates/ruff/resources/test/fixtures/eradicate/ERA001.py index a21d51c4ca94d..56e433f395b13 100644 --- a/crates/ruff/resources/test/fixtures/eradicate/ERA001.py +++ b/crates/ruff/resources/test/fixtures/eradicate/ERA001.py @@ -19,3 +19,12 @@ def foo(x, y, z): class A(): pass # b = c + + +dictionary = { + # "key1": 123, # noqa: ERA001 + # "key2": 456, + # "key3": 789, # test +} + +#import os # noqa diff --git a/crates/ruff/resources/test/fixtures/flake8_annotations/annotation_presence.py b/crates/ruff/resources/test/fixtures/flake8_annotations/annotation_presence.py index 6c512262687ad..36c5155b83e79 100644 --- a/crates/ruff/resources/test/fixtures/flake8_annotations/annotation_presence.py +++ b/crates/ruff/resources/test/fixtures/flake8_annotations/annotation_presence.py @@ -152,3 +152,9 @@ def f(a: Union[str, bytes, Any]) -> None: ... def f(a: Optional[Any]) -> None: ... def f(a: Annotated[Any, ...]) -> None: ... def f(a: "Union[str, bytes, Any]") -> None: ... + + +class Foo: + @decorator() + def __init__(self: "Foo", foo: int): + ... diff --git a/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py b/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py index d60b808cb584a..1689af66e63c5 100644 --- a/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py +++ b/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py @@ -14,3 +14,19 @@ # not ok by config with open("/foo/bar", "w") as f: f.write("def") + +# Using `tempfile` module should be ok +import tempfile +from tempfile import TemporaryDirectory + +with tempfile.NamedTemporaryFile(dir="/tmp") as f: + f.write(b"def") + +with tempfile.NamedTemporaryFile(dir="/var/tmp") as f: + f.write(b"def") + +with tempfile.TemporaryDirectory(dir="/dev/shm") as d: + pass + +with TemporaryDirectory(dir="/tmp") as d: + pass diff --git a/crates/ruff/resources/test/fixtures/flake8_boolean_trap/FBT.py b/crates/ruff/resources/test/fixtures/flake8_boolean_trap/FBT.py index 581668e9320c3..eba1a03097ddf 100644 --- a/crates/ruff/resources/test/fixtures/flake8_boolean_trap/FBT.py +++ b/crates/ruff/resources/test/fixtures/flake8_boolean_trap/FBT.py @@ -67,7 +67,9 @@ def used(do): os.set_blocking(0, False) g_action.set_enabled(True) settings.set_enable_developer_extras(True) - +foo.is_(True) +bar.is_not(False) +next(iter([]), False) class Registry: def __init__(self) -> None: diff --git a/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_B008.py b/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_B008.py index 475506225a876..4b8f8b925b0ea 100644 --- a/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_B008.py +++ b/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_B008.py @@ -68,6 +68,20 @@ def this_is_also_wrong(value={}): ... +class Foo: + @staticmethod + def this_is_also_wrong_and_more_indented(value={}): + pass + + +def multiline_arg_wrong(value={ + +}): + ... + +def single_line_func_wrong(value = {}): ... + + def and_this(value=set()): ... @@ -216,6 +230,10 @@ def timedelta_okay(value=dt.timedelta(hours=1)): def path_okay(value=Path(".")): pass +# B008 allow arbitrary call with immutable annotation +def immutable_annotation_call(value: Sequence[int] = foo()): + pass + # B006 and B008 # We should handle arbitrary nesting of these B008. def nested_combo(a=[float(3), dt.datetime.now()]): @@ -240,12 +258,16 @@ def foo(f=lambda x: print(x)): from collections import abc from typing import Annotated, Dict, Optional, Sequence, Union, Set +import typing_extensions def immutable_annotations( a: Sequence[int] | None = [], b: Optional[abc.Mapping[int, int]] = {}, c: Annotated[Union[abc.Set[str], abc.Sized], "annotation"] = set(), + d: typing_extensions.Annotated[ + Union[abc.Set[str], abc.Sized], "annotation" + ] = set(), ): pass @@ -254,5 +276,35 @@ def mutable_annotations( a: list[int] | None = [], b: Optional[Dict[int, int]] = {}, c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), + d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), ): pass + + +def single_line_func_wrong(value: dict[str, str] = {}): + """Docstring""" + + +def single_line_func_wrong(value: dict[str, str] = {}): + """Docstring""" + ... + + +def single_line_func_wrong(value: dict[str, str] = {}): + """Docstring"""; ... + + +def single_line_func_wrong(value: dict[str, str] = {}): + """Docstring"""; \ + ... + + +def single_line_func_wrong(value: dict[str, str] = { + # This is a comment +}): + """Docstring""" + + +def single_line_func_wrong(value: dict[str, str] = {}) \ + : \ + """Docstring""" diff --git a/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_extended.py b/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_extended.py new file mode 100644 index 0000000000000..15da0cc3fdf00 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_bugbear/B006_extended.py @@ -0,0 +1,18 @@ +import custom +from custom import ImmutableTypeB + + +def okay(foo: ImmutableTypeB = []): + ... + + +def okay(foo: custom.ImmutableTypeA = []): + ... + + +def okay(foo: custom.ImmutableTypeB = []): + ... + + +def error_due_to_missing_import(foo: ImmutableTypeA = []): + ... diff --git a/crates/ruff/resources/test/fixtures/flake8_bugbear/B008_extended.py b/crates/ruff/resources/test/fixtures/flake8_bugbear/B008_extended.py index 941f9dbf50b3e..bf97f793d154f 100644 --- a/crates/ruff/resources/test/fixtures/flake8_bugbear/B008_extended.py +++ b/crates/ruff/resources/test/fixtures/flake8_bugbear/B008_extended.py @@ -1,6 +1,7 @@ from typing import List import fastapi +import custom from fastapi import Query @@ -16,5 +17,9 @@ def okay(data: List[str] = Query(None)): ... +def okay(data: custom.ImmutableTypeA = foo()): + ... + + def error_due_to_missing_import(data: List[str] = Depends(None)): ... diff --git a/crates/ruff/resources/test/fixtures/flake8_bugbear/B014.py b/crates/ruff/resources/test/fixtures/flake8_bugbear/B014.py index 38473457b37f2..8a03e75121c01 100644 --- a/crates/ruff/resources/test/fixtures/flake8_bugbear/B014.py +++ b/crates/ruff/resources/test/fixtures/flake8_bugbear/B014.py @@ -74,3 +74,10 @@ class MyError(Exception): except (ValueError, binascii.Error): # binascii.Error is a subclass of ValueError. pass + + +# https://github.com/astral-sh/ruff/issues/6412 +try: + pass +except (ValueError, ValueError, TypeError): + pass diff --git a/crates/ruff/resources/test/fixtures/flake8_comprehensions/C414.py b/crates/ruff/resources/test/fixtures/flake8_comprehensions/C414.py index 29fb74661ace6..ad61eec08a6fd 100644 --- a/crates/ruff/resources/test/fixtures/flake8_comprehensions/C414.py +++ b/crates/ruff/resources/test/fixtures/flake8_comprehensions/C414.py @@ -22,6 +22,10 @@ "o"] ) ) +set(set()) +set(list()) +set(tuple()) +sorted(reversed()) # Nested sorts with differing keyword arguments. Not flagged. sorted(sorted(x, key=lambda y: y)) diff --git a/crates/ruff/resources/test/fixtures/flake8_comprehensions/C417.py b/crates/ruff/resources/test/fixtures/flake8_comprehensions/C417.py index 7077acfad6bc5..a19c606a58986 100644 --- a/crates/ruff/resources/test/fixtures/flake8_comprehensions/C417.py +++ b/crates/ruff/resources/test/fixtures/flake8_comprehensions/C417.py @@ -15,11 +15,6 @@ _ = f"{set(map(lambda x: x % 2 == 0, nums))}" _ = f"{dict(map(lambda v: (v, v**2), nums))}" -# Error, but unfixable. -# For simple expressions, this could be: `(x if x else 1 for x in nums)`. -# For more complex expressions, this would differ: `(x + 2 if x else 3 for x in nums)`. -map(lambda x=1: x, nums) - # False negatives. map(lambda x=2, y=1: x + y, nums, nums) set(map(lambda x, y: x, nums, nums)) @@ -37,3 +32,8 @@ def func(arg1: int, arg2: int = 4): # Error: the `x` is overridden by the inner lambda. map(lambda x: lambda x: x, range(4)) + +# Ok because of the default parameters, and variadic arguments. +map(lambda x=1: x, nums) +map(lambda *args: len(args), range(4)) +map(lambda **kwargs: len(kwargs), range(4)) diff --git a/crates/ruff/resources/test/fixtures/flake8_import_conventions/defaults.py b/crates/ruff/resources/test/fixtures/flake8_import_conventions/defaults.py index bbaf23ea446db..c1c528deca16e 100644 --- a/crates/ruff/resources/test/fixtures/flake8_import_conventions/defaults.py +++ b/crates/ruff/resources/test/fixtures/flake8_import_conventions/defaults.py @@ -1,22 +1,31 @@ -import math # not checked +def not_checked(): + import math -import altair # unconventional -import matplotlib.pyplot # unconventional -import numpy # unconventional -import pandas # unconventional -import seaborn # unconventional -import tkinter # unconventional -import altair as altr # unconventional -import matplotlib.pyplot as plot # unconventional -import numpy as nmp # unconventional -import pandas as pdas # unconventional -import seaborn as sbrn # unconventional -import tkinter as tkr # unconventional +def unconventional(): + import altair + import matplotlib.pyplot + import numpy + import pandas + import seaborn + import tkinter + import networkx -import altair as alt # conventional -import matplotlib.pyplot as plt # conventional -import numpy as np # conventional -import pandas as pd # conventional -import seaborn as sns # conventional -import tkinter as tk # conventional + +def unconventional_aliases(): + import altair as altr + import matplotlib.pyplot as plot + import numpy as nmp + import pandas as pdas + import seaborn as sbrn + import tkinter as tkr + import networkx as nxy + +def conventional_aliases(): + import altair as alt + import matplotlib.pyplot as plt + import numpy as np + import pandas as pd + import seaborn as sns + import tkinter as tk + import networkx as nx diff --git a/crates/ruff/resources/test/fixtures/flake8_logging_format/G004.py b/crates/ruff/resources/test/fixtures/flake8_logging_format/G004.py index abbbe8b7d04ca..56e005293a62a 100644 --- a/crates/ruff/resources/test/fixtures/flake8_logging_format/G004.py +++ b/crates/ruff/resources/test/fixtures/flake8_logging_format/G004.py @@ -3,3 +3,6 @@ name = "world" logging.info(f"Hello {name}") logging.log(logging.INFO, f"Hello {name}") + +_LOGGER = logging.getLogger() +_LOGGER.info(f"{__name__}") diff --git a/crates/ruff/resources/test/fixtures/flake8_pie/PIE808.py b/crates/ruff/resources/test/fixtures/flake8_pie/PIE808.py new file mode 100644 index 0000000000000..6765a20137f6b --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pie/PIE808.py @@ -0,0 +1,13 @@ +# PIE808 +range(0, 10) + +# OK +range(x, 10) +range(-15, 10) +range(10) +range(0) +range(0, 10, x) +range(0, 10, 1) +range(0, 10, step=1) +range(start=0, stop=10) +range(0, stop=10) diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py index 9c3b530edf0a2..6b11efb181e2d 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py @@ -1,20 +1,19 @@ +import typing + # Shouldn't affect non-union field types. field1: str # Should emit for duplicate field types. field2: str | str # PYI016: Duplicate union member `str` - # Should emit for union types in arguments. def func1(arg1: int | int): # PYI016: Duplicate union member `int` print(arg1) - # Should emit for unions in return types. def func2() -> str | str: # PYI016: Duplicate union member `str` return "my string" - # Should emit in longer unions, even if not directly adjacent. field3: str | str | int # PYI016: Duplicate union member `str` field4: int | int | str # PYI016: Duplicate union member `int` @@ -33,3 +32,55 @@ def func2() -> str | str: # PYI016: Duplicate union member `str` # Should emit for nested unions. field11: dict[int | int, str] + +# Should emit for unions with more than two cases +field12: int | int | int # Error +field13: int | int | int | int # Error + +# Should emit for unions with more than two cases, even if not directly adjacent +field14: int | int | str | int # Error + +# Should emit for duplicate literal types; also covered by PYI030 +field15: typing.Literal[1] | typing.Literal[1] # Error + +# Shouldn't emit if in new parent type +field16: int | dict[int, str] # OK + +# Shouldn't emit if not in a union parent +field17: dict[int, int] # OK + +# Should emit in cases with newlines +field18: typing.Union[ + set[ + int # foo + ], + set[ + int # bar + ], +] # Error, newline and comment will not be emitted in message + +# Should emit in cases with `typing.Union` instead of `|` +field19: typing.Union[int, int] # Error + +# Should emit in cases with nested `typing.Union` +field20: typing.Union[int, typing.Union[int, str]] # Error + +# Should emit in cases with mixed `typing.Union` and `|` +field21: typing.Union[int, int | str] # Error + +# Should emit only once in cases with multiple nested `typing.Union` +field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error + +# Should emit in cases with newlines +field23: set[ # foo + int] | set[int] + +# Should emit twice (once for each `int` in the nested union, both of which are +# duplicates of the outer `int`), but not three times (which would indicate that +# we incorrectly re-checked the nested union). +field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + +# Should emit twice (once for each `int` in the nested union, both of which are +# duplicates of the outer `int`), but not three times (which would indicate that +# we incorrectly re-checked the nested union). +field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi index 1fe4d0a6c712f..6b11efb181e2d 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi @@ -74,3 +74,13 @@ field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error # Should emit in cases with newlines field23: set[ # foo int] | set[int] + +# Should emit twice (once for each `int` in the nested union, both of which are +# duplicates of the outer `int`), but not three times (which would indicate that +# we incorrectly re-checked the nested union). +field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + +# Should emit twice (once for each `int` in the nested union, both of which are +# duplicates of the outer `int`), but not three times (which would indicate that +# we incorrectly re-checked the nested union). +field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.py new file mode 100644 index 0000000000000..23af128a3848d --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.py @@ -0,0 +1,46 @@ +from typing import TypeVar, Self, Type + +_S = TypeVar("_S", bound=BadClass) +_S2 = TypeVar("_S2", BadClass, GoodClass) + +class BadClass: + def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019 + + + def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019 + + + @classmethod + def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019 + + + @classmethod + def bad_posonly_class_method(cls: type[_S], /) -> _S: ... # PYI019 + + + @classmethod + def excluded_edge_case(cls: Type[_S], arg: int) -> _S: ... # Ok + + +class GoodClass: + def __new__(cls: type[Self], *args: list[int], **kwargs: set[str]) -> Self: ... + def good_instance_method_1(self: Self, arg: bytes) -> Self: ... + def good_instance_method_2(self, arg1: _S2, arg2: _S2) -> _S2: ... + @classmethod + def good_cls_method_1(cls: type[Self], arg: int) -> Self: ... + @classmethod + def good_cls_method_2(cls, arg1: _S, arg2: _S) -> _S: ... + @staticmethod + def static_method(arg1: _S) -> _S: ... + + +# Python > 3.12 +class PEP695BadDunderNew[T]: + def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019 + + + def generic_instance_method[S](self: S) -> S: ... # PYI019 + + +class PEP695GoodDunderNew[T]: + def __new__(cls, *args: Any, **kwargs: Any) -> Self: ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.pyi b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.pyi new file mode 100644 index 0000000000000..23af128a3848d --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI019.pyi @@ -0,0 +1,46 @@ +from typing import TypeVar, Self, Type + +_S = TypeVar("_S", bound=BadClass) +_S2 = TypeVar("_S2", BadClass, GoodClass) + +class BadClass: + def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019 + + + def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019 + + + @classmethod + def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019 + + + @classmethod + def bad_posonly_class_method(cls: type[_S], /) -> _S: ... # PYI019 + + + @classmethod + def excluded_edge_case(cls: Type[_S], arg: int) -> _S: ... # Ok + + +class GoodClass: + def __new__(cls: type[Self], *args: list[int], **kwargs: set[str]) -> Self: ... + def good_instance_method_1(self: Self, arg: bytes) -> Self: ... + def good_instance_method_2(self, arg1: _S2, arg2: _S2) -> _S2: ... + @classmethod + def good_cls_method_1(cls: type[Self], arg: int) -> Self: ... + @classmethod + def good_cls_method_2(cls, arg1: _S, arg2: _S) -> _S: ... + @staticmethod + def static_method(arg1: _S) -> _S: ... + + +# Python > 3.12 +class PEP695BadDunderNew[T]: + def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019 + + + def generic_instance_method[S](self: S) -> S: ... # PYI019 + + +class PEP695GoodDunderNew[T]: + def __new__(cls, *args: Any, **kwargs: Any) -> Self: ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI024.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI024.py index 3090ae76c3192..b3d3b67b9ed03 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI024.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI024.py @@ -1,9 +1,11 @@ import collections -person: collections.namedtuple # OK +person: collections.namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" from collections import namedtuple -person: namedtuple # OK +person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" -person = namedtuple("Person", ["name", "age"]) # OK +person = namedtuple( + "Person", ["name", "age"] +) # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI030.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI030.py index cc199f1480479..3c9d0ac15c9c3 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI030.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI030.py @@ -1,24 +1,38 @@ +import typing +import typing_extensions from typing import Literal -# Shouldn't emit for any cases in the non-stub file for compatibility with flake8-pyi. -# Note that this rule could be applied here in the future. +# Shouldn't affect non-union field types. field1: Literal[1] # OK -field2: Literal[1] | Literal[2] # OK -def func1(arg1: Literal[1] | Literal[2]): # OK +# Should emit for duplicate field types. +field2: Literal[1] | Literal[2] # Error + +# Should emit for union types in arguments. +def func1(arg1: Literal[1] | Literal[2]): # Error print(arg1) -def func2() -> Literal[1] | Literal[2]: # OK +# Should emit for unions in return types. +def func2() -> Literal[1] | Literal[2]: # Error return "my Literal[1]ing" -field3: Literal[1] | Literal[2] | str # OK -field4: str | Literal[1] | Literal[2] # OK -field5: Literal[1] | str | Literal[2] # OK -field6: Literal[1] | bool | Literal[2] | str # OK -field7 = Literal[1] | Literal[2] # OK -field8: Literal[1] | (Literal[2] | str) # OK -field9: Literal[1] | (Literal[2] | str) # OK -field10: (Literal[1] | str) | Literal[2] # OK -field11: dict[Literal[1] | Literal[2], str] # OK +# Should emit in longer unions, even if not directly adjacent. +field3: Literal[1] | Literal[2] | str # Error +field4: str | Literal[1] | Literal[2] # Error +field5: Literal[1] | str | Literal[2] # Error +field6: Literal[1] | bool | Literal[2] | str # Error + +# Should emit for non-type unions. +field7 = Literal[1] | Literal[2] # Error + +# Should emit for parenthesized unions. +field8: Literal[1] | (Literal[2] | str) # Error + +# Should handle user parentheses when fixing. +field9: Literal[1] | (Literal[2] | str) # Error +field10: (Literal[1] | str) | Literal[2] # Error + +# Should emit for union in generic parent type. +field11: dict[Literal[1] | Literal[2], str] # Error diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI032.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI032.py index 2d226ebe975f8..82cb899e3b323 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI032.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI032.py @@ -3,8 +3,8 @@ class Bad: - def __eq__(self, other: Any) -> bool: ... # Fine because not a stub file - def __ne__(self, other: typing.Any) -> typing.Any: ... # Fine because not a stub file + def __eq__(self, other: Any) -> bool: ... # Y032 + def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032 class Good: diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py index 8b159057d71eb..2936c39c6c836 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py @@ -9,16 +9,16 @@ just_literals_pipe_union: TypeAlias = ( Literal[True] | Literal["idk"] -) # not PYI042 (not a stubfile) +) # PYI042, since not camel case PublicAliasT: TypeAlias = str | int PublicAliasT2: TypeAlias = Union[str, bytes] _ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any _PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"] _PrivateAliasS2: TypeAlias = Annotated[str, "also okay"] -snake_case_alias1: TypeAlias = str | int # not PYI042 (not a stubfile) -_snake_case_alias2: TypeAlias = Literal["whatever"] # not PYI042 (not a stubfile) -Snake_case_alias: TypeAlias = int | float # not PYI042 (not a stubfile) +snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case +_snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case +Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case # check that this edge case doesn't crash _: TypeAlias = str | int diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py index d129f5befa06b..b48f5e0fa8c47 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py @@ -7,11 +7,11 @@ Literal, ) -_PrivateAliasT: TypeAlias = str | int # not PYI043 (not a stubfile) -_PrivateAliasT2: TypeAlias = typing.Any # not PYI043 (not a stubfile) +_PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T +_PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T _PrivateAliasT3: TypeAlias = Literal[ "not", "a", "chance" -] # not PYI043 (not a stubfile) +] # PYI043, since this ends in a T just_literals_pipe_union: TypeAlias = Literal[True] | Literal["idk"] PublicAliasT: TypeAlias = str | int PublicAliasT2: TypeAlias = Union[str, bytes] diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.py new file mode 100644 index 0000000000000..543c12974c36e --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.py @@ -0,0 +1,17 @@ +import typing +from typing import Literal, TypeAlias, Union + +A: str | Literal["foo"] +B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + +def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + +# OK +A: Literal["foo"] +B: TypeAlias = Literal[b"bar", b"foo"] +C: TypeAlias = typing.Union[Literal[5], Literal["foo"]] +D: TypeAlias = Literal[b"str_bytes", 42] + +def func(x: Literal[1J], y: Literal[3.14]): ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.pyi b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.pyi new file mode 100644 index 0000000000000..543c12974c36e --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI051.pyi @@ -0,0 +1,17 @@ +import typing +from typing import Literal, TypeAlias, Union + +A: str | Literal["foo"] +B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + +def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + +# OK +A: Literal["foo"] +B: TypeAlias = Literal[b"bar", b"foo"] +C: TypeAlias = typing.Union[Literal[5], Literal["foo"]] +D: TypeAlias = Literal[b"str_bytes", 42] + +def func(x: Literal[1J], y: Literal[3.14]): ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.py new file mode 100644 index 0000000000000..adbc1f737a814 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.py @@ -0,0 +1,31 @@ +import builtins +from typing import Union + +w: builtins.type[int] | builtins.type[str] | builtins.type[complex] +x: type[int] | type[str] | type[float] +y: builtins.type[int] | type[str] | builtins.type[complex] +z: Union[type[float], type[complex]] +z: Union[type[float, int], type[complex]] + + +def func(arg: type[int] | str | type[float]) -> None: + ... + + +# OK +x: type[int, str, float] +y: builtins.type[int, str, complex] +z: Union[float, complex] + + +def func(arg: type[int, float] | str) -> None: + ... + + +# OK +item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker + + +def func(): + # PYI055 + item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.pyi b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.pyi new file mode 100644 index 0000000000000..3cc530f770517 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI055.pyi @@ -0,0 +1,24 @@ +import builtins +from typing import Union + +w: builtins.type[int] | builtins.type[str] | builtins.type[complex] +x: type[int] | type[str] | type[float] +y: builtins.type[int] | type[str] | builtins.type[complex] +z: Union[type[float], type[complex]] +z: Union[type[float, int], type[complex]] + +def func(arg: type[int] | str | type[float]) -> None: ... + +# OK +x: type[int, str, float] +y: builtins.type[int, str, complex] +z: Union[float, complex] + +def func(arg: type[int, float] | str) -> None: ... + +# OK +item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker + +def func(): + # PYI055 + item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT006.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT006.py index 3bfac3ecd8316..f444a835efbe5 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT006.py +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT006.py @@ -64,3 +64,8 @@ def test_implicit_str_concat_no_parens(param1, param2, param3): @pytest.mark.parametrize((("param1, " "param2, " "param3")), [(1, 2, 3), (4, 5, 6)]) def test_implicit_str_concat_with_multi_parens(param1, param2, param3): ... + + +@pytest.mark.parametrize(("param1,param2"), [(1, 2), (3, 4)]) +def test_csv_with_parens(param1, param2): + ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT009.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT009.py index e25aef6facff9..128c6b0325729 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT009.py +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT009.py @@ -80,3 +80,15 @@ def test_assert_regexp_matches(self): def test_assert_not_regexp_matches(self): self.assertNotRegex("abc", r"abc") # Error + + def test_fail_if(self): + self.failIf("abc") # Error + + def test_fail_unless(self): + self.failUnless("abc") # Error + + def test_fail_unless_equal(self): + self.failUnlessEqual(1, 2) # Error + + def test_fail_if_equal(self): + self.failIfEqual(1, 2) # Error diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py index 70d877c60eb12..fbec3e2fa0aae 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py @@ -1,3 +1,4 @@ +from pickle import PicklingError, UnpicklingError import socket import pytest @@ -20,6 +21,12 @@ def test_error_no_argument_given(): with pytest.raises(socket.error): raise ValueError("Can't divide 1 by 0") + with pytest.raises(PicklingError): + raise PicklingError("Can't pickle") + + with pytest.raises(UnpicklingError): + raise UnpicklingError("Can't unpickle") + def test_error_match_is_empty(): with pytest.raises(ValueError, match=None): diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT014.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT014.py new file mode 100644 index 0000000000000..b408063d9b235 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT014.py @@ -0,0 +1,53 @@ +import pytest + + +@pytest.mark.parametrize("x", [1, 1, 2]) +def test_error_literal(x): + ... + + +a = 1 +b = 2 +c = 3 + + +@pytest.mark.parametrize("x", [a, a, b, b, b, c]) +def test_error_expr_simple(x): + ... + + +@pytest.mark.parametrize( + "x", + [ + (a, b), + # comment + (a, b), + (b, c), + ], +) +def test_error_expr_complex(x): + ... + + +@pytest.mark.parametrize("x", [a, b, (a), c, ((a))]) +def test_error_parentheses(x): + ... + + +@pytest.mark.parametrize( + "x", + [ + a, + b, + (a), + c, + ((a)), + ], +) +def test_error_parentheses_trailing_comma(x): + ... + + +@pytest.mark.parametrize("x", [1, 2]) +def test_ok(x): + ... diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT018.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT018.py index cedd7ba170c71..4b70bae72e36a 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT018.py +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT018.py @@ -43,3 +43,12 @@ def test_error(): assert something # OK assert something and something_else # Error assert something and something_else and something_third # Error + + +def test_multiline(): + assert something and something_else; x = 1 + + x = 1; assert something and something_else + + x = 1; \ + assert something and something_else diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_0.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_0.py new file mode 100644 index 0000000000000..b9614f0647dc1 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_0.py @@ -0,0 +1,48 @@ +import unittest + + +class Test(unittest.TestCase): + def test_errors(self): + with self.assertRaises(ValueError): + raise ValueError + with self.assertRaises(expected_exception=ValueError): + raise ValueError + + with self.failUnlessRaises(ValueError): + raise ValueError + + with self.assertRaisesRegex(ValueError, "test"): + raise ValueError("test") + + with self.assertRaisesRegex(ValueError, expected_regex="test"): + raise ValueError("test") + + with self.assertRaisesRegex( + expected_exception=ValueError, expected_regex="test" + ): + raise ValueError("test") + + with self.assertRaisesRegex( + expected_regex="test", expected_exception=ValueError + ): + raise ValueError("test") + + with self.assertRaisesRegexp(ValueError, "test"): + raise ValueError("test") + + def test_unfixable_errors(self): + with self.assertRaises(ValueError, msg="msg"): + raise ValueError + + with self.assertRaises( + # comment + ValueError + ): + raise ValueError + + with ( + self + # comment + .assertRaises(ValueError) + ): + raise ValueError diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_1.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_1.py new file mode 100644 index 0000000000000..708a582ad3d22 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT027_1.py @@ -0,0 +1,12 @@ +import unittest +import pytest + + +class Test(unittest.TestCase): + def test_pytest_raises(self): + with pytest.raises(ValueError): + raise ValueError + + def test_errors(self): + with self.assertRaises(ValueError): + raise ValueError diff --git a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py index ce75d7ab7c179..5ef0b007c335e 100644 --- a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py +++ b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py @@ -19,11 +19,20 @@ raise TypeError \ () +# RSE102 +raise TypeError \ + (); + # RSE102 raise TypeError( ) +# RSE102 +raise (TypeError) ( + +) + # RSE102 raise TypeError( # Hello, world! @@ -52,3 +61,10 @@ def error(): # OK raise Class.error() + + +import ctypes + + +# OK +raise ctypes.WinError(1) diff --git a/crates/ruff/resources/test/fixtures/flake8_return/RET503.py b/crates/ruff/resources/test/fixtures/flake8_return/RET503.py index 77d59cd8d48e9..9ec90617d31c4 100644 --- a/crates/ruff/resources/test/fixtures/flake8_return/RET503.py +++ b/crates/ruff/resources/test/fixtures/flake8_return/RET503.py @@ -320,3 +320,9 @@ def example(): if True: return "" \ ; # type: ignore + + +def end_of_file(): + if False: + return 1 + x = 2 \ diff --git a/crates/ruff/resources/test/fixtures/flake8_self/SLF001.py b/crates/ruff/resources/test/fixtures/flake8_self/SLF001.py index 5735e63751e2b..0a5a560182df3 100644 --- a/crates/ruff/resources/test/fixtures/flake8_self/SLF001.py +++ b/crates/ruff/resources/test/fixtures/flake8_self/SLF001.py @@ -73,3 +73,7 @@ def __eq__(self, other): print(foo.__str__()) print(foo().__class__) print(foo._asdict()) + +import os + +os._exit() diff --git a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py index 6f86a62204bec..182412e5452cb 100644 --- a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py +++ b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM118.py @@ -31,6 +31,8 @@ key in (obj or {}).keys() # SIM118 +(key) in (obj or {}).keys() # SIM118 + from typing import KeysView diff --git a/crates/ruff/resources/test/fixtures/flake8_tidy_imports/TID253.py b/crates/ruff/resources/test/fixtures/flake8_tidy_imports/TID253.py new file mode 100644 index 0000000000000..d0d3d14845f9a --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_tidy_imports/TID253.py @@ -0,0 +1,31 @@ +## Banned modules ## +import torch + +from torch import * + +from tensorflow import a, b, c + +import torch as torch_wearing_a_trenchcoat + +# this should count as module level +x = 1; import tensorflow + +# banning a module also bans any submodules +import torch.foo.bar + +from tensorflow.foo import bar + +from torch.foo.bar import * + +# unlike TID251, inline imports are *not* banned +def my_cool_function(): + import tensorflow.foo.bar + +def another_cool_function(): + from torch.foo import bar + +def import_alias(): + from torch.foo import bar + +if TYPE_CHECKING: + import torch diff --git a/crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_4.py b/crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_4.py new file mode 100644 index 0000000000000..55da289edc9ab --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_4.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from datetime import date + +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + + +class Birthday(DeclarativeBase): + + __tablename__ = "birthday" + id: Mapped[int] = mapped_column(primary_key=True) + day: Mapped[date] diff --git a/crates/ruff/resources/test/fixtures/flake8_unused_arguments/ARG.py b/crates/ruff/resources/test/fixtures/flake8_unused_arguments/ARG.py index 3aac4018c8489..9a8fd4c83585c 100644 --- a/crates/ruff/resources/test/fixtures/flake8_unused_arguments/ARG.py +++ b/crates/ruff/resources/test/fixtures/flake8_unused_arguments/ARG.py @@ -27,6 +27,8 @@ def f(cls, x): ### lambda x: print("Hello, world!") +lambda: print("Hello, world!") + class C: ### @@ -202,3 +204,14 @@ def __exit__(self, exc_type, exc_value, traceback) -> None: ### def f(x: None) -> None: _ = cast(Any, _identity)(x=x) + +### +# Unused arguments with `locals`. +### +def f(bar: str): + print(locals()) + + +class C: + def __init__(self, x) -> None: + print(locals()) diff --git a/crates/ruff/resources/test/fixtures/flake8_use_pathlib/PTH206.py b/crates/ruff/resources/test/fixtures/flake8_use_pathlib/PTH206.py index 946d2061d000a..adddd50333d02 100644 --- a/crates/ruff/resources/test/fixtures/flake8_use_pathlib/PTH206.py +++ b/crates/ruff/resources/test/fixtures/flake8_use_pathlib/PTH206.py @@ -18,3 +18,5 @@ # OK "foo/bar/".split("/") +"foo/bar/".split(os.sep, 1) +"foo/bar/".split(1, sep=os.sep) diff --git a/crates/ruff/resources/test/fixtures/isort/detect_same_package/foo/__init__.py b/crates/ruff/resources/test/fixtures/isort/detect_same_package/foo/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/crates/ruff/resources/test/fixtures/isort/detect_same_package/foo/bar.py b/crates/ruff/resources/test/fixtures/isort/detect_same_package/foo/bar.py new file mode 100644 index 0000000000000..b51f130ac15b1 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/isort/detect_same_package/foo/bar.py @@ -0,0 +1,3 @@ +import os +import pandas +import foo.baz diff --git a/crates/ruff/resources/test/fixtures/isort/detect_same_package/pyproject.toml b/crates/ruff/resources/test/fixtures/isort/detect_same_package/pyproject.toml new file mode 100644 index 0000000000000..97fda9d62e0a9 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/isort/detect_same_package/pyproject.toml @@ -0,0 +1,2 @@ +[tool.ruff] +line-length = 88 diff --git a/crates/ruff/resources/test/fixtures/isort/required_imports/comments_and_newlines.py b/crates/ruff/resources/test/fixtures/isort/required_imports/comments_and_newlines.py new file mode 100644 index 0000000000000..5d2462ab9f966 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/isort/required_imports/comments_and_newlines.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +# A copyright notice could go here + +# A linter directive could go here + +x = 1 diff --git a/crates/ruff/resources/test/fixtures/jupyter/add_missing_cell_id.ipynb b/crates/ruff/resources/test/fixtures/jupyter/add_missing_cell_id.ipynb new file mode 100644 index 0000000000000..d1adfcefe2c11 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/add_missing_cell_id.ipynb @@ -0,0 +1,37 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import os\n", + "\n", + "math.pi" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/cell/cell_magic.json b/crates/ruff/resources/test/fixtures/jupyter/cell/cell_magic.json new file mode 100644 index 0000000000000..ef68b202e6811 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/cell/cell_magic.json @@ -0,0 +1,8 @@ +{ + "execution_count": null, + "cell_type": "code", + "id": "1", + "metadata": {}, + "outputs": [], + "source": ["%%timeit\n", "print('hello world')"] +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command.ipynb b/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command.ipynb new file mode 100644 index 0000000000000..5e9b10bb7b0e1 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command.ipynb @@ -0,0 +1,52 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "eab4754a-d6df-4b41-8ee8-7e23aef440f9", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "\n", + "%matplotlib inline\n", + "\n", + "import os\n", + "\n", + "_ = math.pi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b0e2986-1b87-4bb6-9b1d-c11ca1decd87", + "metadata": {}, + "outputs": [], + "source": [ + "%%timeit\n", + "import sys" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command_expected.ipynb b/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command_expected.ipynb new file mode 100644 index 0000000000000..8419f031e78f8 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/ipy_escape_command_expected.ipynb @@ -0,0 +1,51 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "cad32845-44f9-4a53-8b8c-a6b1bb3f3378", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "\n", + "%matplotlib inline\n", + "\n", + "\n", + "_ = math.pi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7b8e967-8b4a-493b-b6f7-d5cecfb3a5c3", + "metadata": {}, + "outputs": [], + "source": [ + "%%timeit\n", + "import sys" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/isort.ipynb b/crates/ruff/resources/test/fixtures/jupyter/isort.ipynb index aef5ff2e8b8aa..9572f7b25e8ad 100644 --- a/crates/ruff/resources/test/fixtures/jupyter/isort.ipynb +++ b/crates/ruff/resources/test/fixtures/jupyter/isort.ipynb @@ -25,6 +25,23 @@ "def foo():\n", " pass" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16214f6f-bb32-4594-81be-79fb27c6ec92", + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "import sys\n", + "\n", + "%matplotlib \\\n", + " --inline\n", + "\n", + "import math\n", + "import abc" + ] } ], "metadata": { diff --git a/crates/ruff/resources/test/fixtures/jupyter/isort_expected.ipynb b/crates/ruff/resources/test/fixtures/jupyter/isort_expected.ipynb index 009c598e71672..5118aa36615e2 100644 --- a/crates/ruff/resources/test/fixtures/jupyter/isort_expected.ipynb +++ b/crates/ruff/resources/test/fixtures/jupyter/isort_expected.ipynb @@ -27,6 +27,23 @@ "def foo():\n", " pass" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6d6c55c6-4a34-4662-914b-4ee11c9c24a5", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "from pathlib import Path\n", + "\n", + "%matplotlib \\\n", + " --inline\n", + "\n", + "import abc\n", + "import math" + ] } ], "metadata": { diff --git a/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb b/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb new file mode 100644 index 0000000000000..ea9e9e654af2b --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb @@ -0,0 +1,37 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import os\n", + "\n", + "math.pi" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/unused_variable.ipynb b/crates/ruff/resources/test/fixtures/jupyter/unused_variable.ipynb new file mode 100644 index 0000000000000..d4b2f8f8af78d --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/unused_variable.ipynb @@ -0,0 +1,49 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a0efffbc-85f1-4513-bf49-5387ec3a2a4e", + "metadata": {}, + "outputs": [], + "source": [ + "def f():\n", + " foo1 = %matplotlib --list\n", + " foo2: list[str] = %matplotlib --list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e0b2b50-43f2-4f59-951d-9404dd560ae4", + "metadata": {}, + "outputs": [], + "source": [ + "def f():\n", + " bar1 = !pwd\n", + " bar2: str = !pwd" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/crates/ruff/resources/test/fixtures/jupyter/unused_variable_expected.ipynb b/crates/ruff/resources/test/fixtures/jupyter/unused_variable_expected.ipynb new file mode 100644 index 0000000000000..0c68e77de6179 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/unused_variable_expected.ipynb @@ -0,0 +1,49 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "24426ef2-046c-453e-b809-05b56e7355e0", + "metadata": {}, + "outputs": [], + "source": [ + "def f():\n", + " %matplotlib --list\n", + " %matplotlib --list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d98fdae-b86b-476e-b4db-9d3ce5562682", + "metadata": {}, + "outputs": [], + "source": [ + "def f():\n", + " !pwd\n", + " !pwd" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/crates/ruff/resources/test/fixtures/perflint/PERF203.py b/crates/ruff/resources/test/fixtures/perflint/PERF203.py index 14b3fa38a3800..8a82c3c249ee2 100644 --- a/crates/ruff/resources/test/fixtures/perflint/PERF203.py +++ b/crates/ruff/resources/test/fixtures/perflint/PERF203.py @@ -21,3 +21,29 @@ print("error") i += 1 + +# OK - no other way to write this +for i in range(10): + try: + print(f"{i}") + break + except: + print("error") + +# OK - no other way to write this +for i in range(10): + try: + print(f"{i}") + continue + except: + print("error") + + +# OK - no other way to write this +for i in range(10): + try: + print(f"{i}") + if i > 0: + break + except: + print("error") diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E23.py b/crates/ruff/resources/test/fixtures/pycodestyle/E23.py index e2c6b9fe661a1..d2bb50b05d023 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E23.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E23.py @@ -28,3 +28,6 @@ def foo() -> None: 'tag_full': [('mdtype', 'u4'), ('byte_count', 'u4')], 'tag_smalldata':[('byte_count_mdtype', 'u4'), ('data', 'S4')], } + +#: Okay +a = (1, diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E402.py b/crates/ruff/resources/test/fixtures/pycodestyle/E402.py index 81e6306c7af11..d5943407852a2 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E402.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E402.py @@ -30,3 +30,10 @@ def foo() -> None: if __name__ == "__main__": import g + +import h; import i + + +if __name__ == "__main__": + import j; \ +import k diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E501_2.py b/crates/ruff/resources/test/fixtures/pycodestyle/E501_2.py index 18ea839392ba1..617b3ad7dc7c9 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E501_2.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E501_2.py @@ -1,11 +1,16 @@ -a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +# aaaa +# aaaaa + # a + # a + # aa + # aaa + # aaaa + # a + # aa + # aaa -b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - -c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - -d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +if True: # noqa: E501 + [12] + [12 ] + [1,2] + [1, 2] diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E712.py b/crates/ruff/resources/test/fixtures/pycodestyle/E712.py index 818afddaefe95..c0be4d7aa1c47 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E712.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E712.py @@ -25,6 +25,12 @@ if res == True != False: pass +if(True) == TrueElement or x == TrueElement: + pass + +if (yield i) == True: + print("even") + #: Okay if x not in y: pass diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E721.py b/crates/ruff/resources/test/fixtures/pycodestyle/E721.py index a220f58c3d8e4..6eacc0cb0c9ab 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E721.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E721.py @@ -58,3 +58,33 @@ types = StrEnum if x == types.X: pass + +#: E721 +assert type(res) is int + + +class Foo: + def asdf(self, value: str | None): + #: E721 + if type(value) is str: + ... + + +class Foo: + def type(self): + pass + + def asdf(self, value: str | None): + #: E721 + if type(value) is str: + ... + + +class Foo: + def asdf(self, value: str | None): + def type(): + pass + + # Okay + if type(value) is str: + ... diff --git a/crates/ruff/resources/test/fixtures/pycodestyle/E731.py b/crates/ruff/resources/test/fixtures/pycodestyle/E731.py index c207c7dae9262..2cb4c7ea3acb4 100644 --- a/crates/ruff/resources/test/fixtures/pycodestyle/E731.py +++ b/crates/ruff/resources/test/fixtures/pycodestyle/E731.py @@ -133,3 +133,8 @@ def scope(): from collections.abc import Callable f: Callable[[str, int, list[str]], list[str]] = lambda a, b, /, c: [*c, a * b] + + +class TemperatureScales(Enum): + CELSIUS = (lambda deg_c: deg_c) + FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32) diff --git a/crates/ruff/resources/test/fixtures/pydocstyle/D.py b/crates/ruff/resources/test/fixtures/pydocstyle/D.py index 94abc1c906f2e..23a74c381f42e 100644 --- a/crates/ruff/resources/test/fixtures/pydocstyle/D.py +++ b/crates/ruff/resources/test/fixtures/pydocstyle/D.py @@ -634,3 +634,8 @@ def starts_with_this(): @expect('D404: First word of the docstring should not be "This"') def starts_with_space_then_this(): """ This is a docstring that starts with a space.""" # noqa: D210 + + +class SameLine: """This is a docstring on the same line""" + +def same_line(): """This is a docstring on the same line""" diff --git a/crates/ruff/resources/test/fixtures/pydocstyle/D200.py b/crates/ruff/resources/test/fixtures/pydocstyle/D200.py new file mode 100644 index 0000000000000..f76c66e631596 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pydocstyle/D200.py @@ -0,0 +1,13 @@ +def func(): + """\ + """ + + +def func(): + """\\ + """ + + +def func(): + """\ \ + """ diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F401_0.py b/crates/ruff/resources/test/fixtures/pyflakes/F401_0.py index 79c56bc09910a..c3a2db56f73b6 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F401_0.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F401_0.py @@ -92,3 +92,23 @@ def b(self) -> None: case 0,: import x import y + + +# Test: access a sub-importation via an alias. +import foo.bar as bop +import foo.bar.baz + +print(bop.baz.read_csv("test.csv")) + +# Test: isolated deletions. +if TYPE_CHECKING: + import a1 + + import a2 + + +match *0, 1, *2: + case 0,: + import b1 + + import b2 diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F522.py b/crates/ruff/resources/test/fixtures/pyflakes/F522.py index 18e3d072f26a1..d229b23e451d0 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F522.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F522.py @@ -2,6 +2,5 @@ "{bar}{}".format(1, bar=2, spam=3) # F522 "{bar:{spam}}".format(bar=2, spam=3) # No issues "{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 -# Not fixable ('' - .format(x=2)) \ No newline at end of file + .format(x=2)) # F522 diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F523.py b/crates/ruff/resources/test/fixtures/pyflakes/F523.py index d3dd1b68db7d1..94dbe7bb2911c 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F523.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F523.py @@ -28,6 +28,6 @@ "{1}{3}".format(1, 2, 3, 4) # F523, # F524 "{1} {8}".format(0, 1) # F523, # F524 -# Not fixable +# Multiline ('' .format(2)) diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F823.py b/crates/ruff/resources/test/fixtures/pyflakes/F823.py index 343150143e442..d6c5ee7d444f5 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F823.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F823.py @@ -70,3 +70,13 @@ def main(): def requests_mock(requests_mock: rm.Mocker): print(rm.ANY) + + +import sklearn.base +import mlflow.sklearn + + +def f(): + import sklearn + + mlflow diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F841_0.py b/crates/ruff/resources/test/fixtures/pyflakes/F841_0.py index 94bc0b6ca507d..bde71536966f4 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F841_0.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F841_0.py @@ -145,3 +145,9 @@ def do_thing(self): obj = Foo() obj.do_thing() + +def f(): + try: + pass + except Exception as _: + pass diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F841_3.py b/crates/ruff/resources/test/fixtures/pyflakes/F841_3.py index a2e6c623f7fe1..ce7b19a1b3c63 100644 --- a/crates/ruff/resources/test/fixtures/pyflakes/F841_3.py +++ b/crates/ruff/resources/test/fixtures/pyflakes/F841_3.py @@ -154,3 +154,14 @@ def f() -> None: print("hello") except A as e : print("oh no!") + + +def f(): + x = 1 + y = 2 + + +def f(): + x = 1 + + y = 2 diff --git a/crates/ruff/resources/test/fixtures/pylint/bad_dunder_method_name.py b/crates/ruff/resources/test/fixtures/pylint/bad_dunder_method_name.py new file mode 100644 index 0000000000000..46d8be249bc95 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pylint/bad_dunder_method_name.py @@ -0,0 +1,46 @@ +class Apples: + def _init_(self): # [bad-dunder-name] + pass + + def __hello__(self): # [bad-dunder-name] + print("hello") + + def __init_(self): # [bad-dunder-name] + # author likely unintentionally misspelled the correct init dunder. + pass + + def _init_(self): # [bad-dunder-name] + # author likely unintentionally misspelled the correct init dunder. + pass + + def ___neg__(self): # [bad-dunder-name] + # author likely accidentally added an additional `_` + pass + + def __inv__(self): # [bad-dunder-name] + # author likely meant to call the invert dunder method + pass + + def hello(self): + print("hello") + + def __init__(self): + pass + + def init(self): + # valid name even though someone could accidentally mean __init__ + pass + + def _protected_method(self): + print("Protected") + + def __private_method(self): + print("Private") + + @property + def __doc__(self): + return "Docstring" + + +def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule + ... diff --git a/crates/ruff/resources/test/fixtures/pylint/bad_string_format_character.py b/crates/ruff/resources/test/fixtures/pylint/bad_string_format_character.py new file mode 100644 index 0000000000000..cffe53d7234ea --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pylint/bad_string_format_character.py @@ -0,0 +1,34 @@ +# pylint: disable=missing-docstring,consider-using-f-string, pointless-statement + +## Old style formatting + +"%s %z" % ("hello", "world") # [bad-format-character] + +"%s" "%z" % ("hello", "world") # [bad-format-character] + +"""%s %z""" % ("hello", "world") # [bad-format-character] + +"""%s""" """%z""" % ("hello", "world") # [bad-format-character] + +## New style formatting + +"{:s} {:y}".format("hello", "world") # [bad-format-character] + +"{:*^30s}".format("centered") # OK +"{:{s}}".format("hello", s="s") # OK (nested placeholder value not checked) +"{:{s:y}}".format("hello", s="s") # [bad-format-character] (nested placeholder format spec checked) +"{0:.{prec}g}".format(1.23, prec=15) # OK (cannot validate after nested placeholder) +"{0:.{foo}{bar}{foobar}y}".format(...) # OK (cannot validate after nested placeholders) +"{0:.{foo}x{bar}y{foobar}g}".format(...) # OK (all nested placeholders are consumed without considering in between chars) + +## f-strings + +H, W = "hello", "world" +f"{H} {W}" +f"{H:s} {W:z}" # [bad-format-character] + +f"{1:z}" # [bad-format-character] + +## False negatives + +print(("%" "z") % 1) diff --git a/crates/ruff/resources/test/fixtures/pylint/bad_string_format_type.py b/crates/ruff/resources/test/fixtures/pylint/bad_string_format_type.py index 66d6f2a5fd203..3fe6722401507 100644 --- a/crates/ruff/resources/test/fixtures/pylint/bad_string_format_type.py +++ b/crates/ruff/resources/test/fixtures/pylint/bad_string_format_type.py @@ -13,6 +13,7 @@ "%(key)d" % {"key": []} print("%d" % ("%s" % ("nested",),)) "%d" % ((1, 2, 3),) +"%d" % (1 if x > 0 else []) # False negatives WORD = "abc" @@ -55,3 +56,4 @@ "%d" % (len(foo),) '(%r, %r, %r, %r)' % (hostname, address, username, '$PASSWORD') '%r' % ({'server_school_roles': server_school_roles, 'is_school_multiserver_domain': is_school_multiserver_domain}, ) +"%d" % (1 if x > 0 else 2) diff --git a/crates/ruff/resources/test/fixtures/pylint/comparison_with_itself.py b/crates/ruff/resources/test/fixtures/pylint/comparison_with_itself.py index e6505608a03ee..066ddb7c846ce 100644 --- a/crates/ruff/resources/test/fixtures/pylint/comparison_with_itself.py +++ b/crates/ruff/resources/test/fixtures/pylint/comparison_with_itself.py @@ -19,6 +19,10 @@ foo not in foo +id(foo) == id(foo) + +len(foo) == len(foo) + # Non-errors. "foo" == "foo" # This is flagged by `comparison-of-constant` instead. @@ -43,3 +47,11 @@ foo in bar foo not in bar + +x(foo) == y(foo) + +id(foo) == id(bar) + +id(foo, bar) == id(foo, bar) + +id(foo, bar=1) == id(foo, bar=1) diff --git a/crates/ruff/resources/test/fixtures/pylint/eq_without_hash.py b/crates/ruff/resources/test/fixtures/pylint/eq_without_hash.py index 44a62f3b7aa6a..f34c90e4dc3c9 100644 --- a/crates/ruff/resources/test/fixtures/pylint/eq_without_hash.py +++ b/crates/ruff/resources/test/fixtures/pylint/eq_without_hash.py @@ -1,10 +1,11 @@ -class Person: +class Person: # [eq-without-hash] def __init__(self): self.name = "monty" def __eq__(self, other): return isinstance(other, Person) and other.name == self.name +# OK class Language: def __init__(self): self.name = "python" @@ -14,3 +15,9 @@ def __eq__(self, other): def __hash__(self): return hash(self.name) + +class MyClass: + def __eq__(self, other): + return True + + __hash__ = None diff --git a/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py b/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py index 9054087de431a..fc7a3f8e154fa 100644 --- a/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py +++ b/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py @@ -40,3 +40,4 @@ __all__ = __all__ + multiprocessing.__all__ +__all__ = list[str](["Hello", "world"]) diff --git a/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py b/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py index c07de79871fda..9aa486678e48f 100644 --- a/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py +++ b/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py @@ -10,3 +10,4 @@ os.getenv("AA", "GOOD" + 1) os.getenv("AA", "GOOD %s" % "BAD") os.getenv("B", Z) + diff --git a/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py b/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py index 23574d7b773c6..86de9053406bb 100644 --- a/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py +++ b/crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py @@ -10,6 +10,8 @@ os.getenv(key=f"foo", default="bar") os.getenv(key="foo" + "bar", default=1) os.getenv(key=1 + "bar", default=1) # [invalid-envvar-value] +os.getenv("PATH_TEST" if using_clear_path else "PATH_ORIG") +os.getenv(1 if using_clear_path else "PATH_ORIG") AA = "aa" os.getenv(AA) diff --git a/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py b/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py index 2fc6f49ab5756..65f021ea428e1 100644 --- a/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py +++ b/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py @@ -19,6 +19,10 @@ # do not handle keyword arguments logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d") +logging.info(msg="Hello %s") + +logging.info(msg="Hello %s %s") + import warning warning.warning("Hello %s %s", "World!") diff --git a/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py b/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py index c087b05c4e900..c64641eaed224 100644 --- a/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py +++ b/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py @@ -15,6 +15,10 @@ # do not handle keyword arguments logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d", {"objects": 1, "modifications": 1, "errors": 1}) +logging.info(msg="Hello") + +logging.info(msg="Hello", something="else") + import warning warning.warning("Hello %s", "World!", "again") diff --git a/crates/ruff/resources/test/fixtures/pylint/no_self_use.py b/crates/ruff/resources/test/fixtures/pylint/no_self_use.py new file mode 100644 index 0000000000000..33524c5916fcc --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pylint/no_self_use.py @@ -0,0 +1,62 @@ +import abc + + +class Person: + def developer_greeting(self, name): # [no-self-use] + print(f"Greetings {name}!") + + def greeting_1(self): # [no-self-use] + print("Hello!") + + def greeting_2(self): # [no-self-use] + print("Hi!") + + +# OK +def developer_greeting(): + print("Greetings developer!") + + +# OK +class Person: + name = "Paris" + + def __init__(self): + pass + + def __cmp__(self, other): + print(24) + + def __repr__(self): + return "Person" + + def func(self): + ... + + def greeting_1(self): + print(f"Hello from {self.name} !") + + @staticmethod + def greeting_2(): + print("Hi!") + + +class Base(abc.ABC): + """abstract class""" + + @abstractmethod + def abstract_method(self): + """abstract method could not be a function""" + raise NotImplementedError + + +class Sub(Base): + @override + def abstract_method(self): + print("concret method") + + +class Prop: + @property + def count(self): + return 24 diff --git a/crates/ruff/resources/test/fixtures/pylint/repeated_equality_comparison_target.py b/crates/ruff/resources/test/fixtures/pylint/repeated_equality_comparison_target.py index f82e19a761da4..6c3f694ba87cd 100644 --- a/crates/ruff/resources/test/fixtures/pylint/repeated_equality_comparison_target.py +++ b/crates/ruff/resources/test/fixtures/pylint/repeated_equality_comparison_target.py @@ -9,13 +9,22 @@ foo == a or foo == "b" or foo == 3 # Mixed types. -# False negatives (the current implementation doesn't support Yoda conditions). "a" == foo or "b" == foo or "c" == foo "a" != foo and "b" != foo and "c" != foo "a" == foo or foo == "b" or "c" == foo +foo == bar or baz == foo or qux == foo + +foo == "a" or "b" == foo or foo == "c" + +foo != "a" and "b" != foo and foo != "c" + +foo == "a" or foo == "b" or "c" == bar or "d" == bar # Multiple targets + +foo.bar == "a" or foo.bar == "b" # Attributes. + # OK foo == "a" and foo == "b" and foo == "c" # `and` mixed with `==`. @@ -32,3 +41,13 @@ foo == "a" # Single comparison. foo != "a" # Single comparison. + +foo == "a" == "b" or foo == "c" # Multiple comparisons. + +foo == bar == "b" or foo == "c" # Multiple comparisons. + +foo == foo or foo == bar # Self-comparison. + +foo[0] == "a" or foo[0] == "b" # Subscripts. + +foo() == "a" or foo() == "b" # Calls. diff --git a/crates/ruff/resources/test/fixtures/pylint/subprocess_run_without_check.py b/crates/ruff/resources/test/fixtures/pylint/subprocess_run_without_check.py new file mode 100644 index 0000000000000..b329ba45109ab --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pylint/subprocess_run_without_check.py @@ -0,0 +1,13 @@ +import subprocess + +# Errors. +subprocess.run("ls") +subprocess.run("ls", shell=True) + +# Non-errors. +subprocess.run("ls", check=True) +subprocess.run("ls", check=False) +subprocess.run("ls", shell=True, check=True) +subprocess.run("ls", shell=True, check=False) +foo.run("ls") # Not a subprocess.run call. +subprocess.bar("ls") # Not a subprocess.run call. diff --git a/crates/ruff/resources/test/fixtures/pylint/sys_exit_alias_11.py b/crates/ruff/resources/test/fixtures/pylint/sys_exit_alias_11.py new file mode 100644 index 0000000000000..775747f9f8fcd --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pylint/sys_exit_alias_11.py @@ -0,0 +1,3 @@ +from sys import * + +exit(0) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP009_10.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_10.py new file mode 100644 index 0000000000000..bfb26d1717ab9 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_10.py @@ -0,0 +1,7 @@ +""" +# coding=utf8""" # empty comment + +""" +Invalid coding declaration since it is nested inside a docstring +The following empty comment tests for false positives as our implementation visits comments +""" diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP009_6.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_6.py new file mode 100644 index 0000000000000..d1900e39bbbc9 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_6.py @@ -0,0 +1,7 @@ + # coding=utf8 +print("Hello world") + +""" +Regression test for https://github.com/astral-sh/ruff/issues/6756 +The leading space must be removed to prevent invalid syntax. +""" diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP009_7.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_7.py new file mode 100644 index 0000000000000..5433482dd8912 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_7.py @@ -0,0 +1,7 @@ + # coding=utf8 +print("Hello world") + +""" +Regression test for https://github.com/astral-sh/ruff/issues/6756 +The leading tab must be removed to prevent invalid syntax. +""" diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP009_8.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_8.py new file mode 100644 index 0000000000000..e0e48475bf907 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_8.py @@ -0,0 +1,6 @@ +print("foo") # coding=utf8 +print("Hello world") + +""" +Invalid coding declaration due to a statement before the comment +""" diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP009_9.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_9.py new file mode 100644 index 0000000000000..b88d6cb794c08 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP009_9.py @@ -0,0 +1,7 @@ +x = 1 \ + # coding=utf8 +x = 2 + +""" +Invalid coding declaration due to continuation on preceding line +""" diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP018.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP018.py index b9a57271146cf..0dfb97566664e 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP018.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP018.py @@ -31,6 +31,7 @@ bool("") bool(b"") bool(1.0) +int().denominator # These become string or byte literals str() @@ -49,3 +50,6 @@ bool() bool(True) bool(False) + +# These become a literal but retain parentheses +int(1).denominator diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP030_0.py index 35b85eb3cc3e3..37e3ba4d49d4f 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP030_0.py @@ -32,3 +32,30 @@ ) '{' '0}'.format(1) + +args = list(range(10)) +kwargs = {x: x for x in range(10)} + +"{0}".format(*args) + +"{0}".format(**kwargs) + +"{0}_{1}".format(*args) + +"{0}_{1}".format(1, *args) + +"{0}_{1}".format(1, 2, *args) + +"{0}_{1}".format(*args, 1, 2) + +"{0}_{1}_{2}".format(1, **kwargs) + +"{0}_{1}_{2}".format(1, 2, **kwargs) + +"{0}_{1}_{2}".format(1, 2, 3, **kwargs) + +"{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) + +"{1}_{0}".format(1, 2, *args) + +"{1}_{0}".format(1, 2) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_1.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP030_1.py index 85fcf311f5c81..5cb750ece9c1c 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_1.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP030_1.py @@ -15,3 +15,17 @@ print(f"{0}".format(1)) ''.format(1) + +'{1} {0}'.format(*args) + +"{1}_{0}".format(*args, 1) + +"{1}_{0}".format(*args, 1, 2) + +"{1}_{0}".format(1, **kwargs) + +"{1}_{0}".format(1, foo=2) + +"{1}_{0}".format(1, 2, **kwargs) + +"{1}_{0}".format(1, 2, foo=3, bar=4) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_2.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP030_2.py deleted file mode 100644 index 30f2d0c8863da..0000000000000 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP030_2.py +++ /dev/null @@ -1,28 +0,0 @@ -# These SHOULD change - -args = list(range(10)) -kwargs = {x: x for x in range(10)} - -"{0}".format(*args) - -"{0}".format(**kwargs) - -"{0}_{1}".format(*args) - -"{0}_{1}".format(1, *args) - -"{1}_{0}".format(*args) - -"{1}_{0}".format(1, *args) - -"{0}_{1}".format(1, 2, *args) - -"{0}_{1}".format(*args, 1, 2) - -"{0}_{1}_{2}".format(1, **kwargs) - -"{0}_{1}_{2}".format(1, 2, **kwargs) - -"{0}_{1}_{2}".format(1, 2, 3, **kwargs) - -"{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP031_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP031_0.py index dadc9bf37d9c5..9544e11c4c632 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP031_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP031_0.py @@ -106,3 +106,7 @@ """ % (x,) ) + +"%s" % ( + x, # comment +) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py index 6f1bef19ab0ea..e6f9b426fab0b 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP032_0.py @@ -6,8 +6,12 @@ "{1} {0}".format(a, b) +"{0} {1} {0}".format(a, b) + "{x.y}".format(x=z) +"{x} {y} {x}".format(x=a, y=b) + "{.x} {.y}".format(a, b) "{} {}".format(a.b, c.d) @@ -72,6 +76,58 @@ 111111 ) +"{a}" "{b}".format(a=1, b=1) + +( + "{a}" + "{b}" +).format(a=1, b=1) + +( + "{a}" + "" + "{b}" + "" +).format(a=1, b=1) + +( + ( + # comment + "{a}" + # comment + "{b}" + ) + # comment + .format(a=1, b=1) +) + +( + "{a}" + "b" +).format(a=1) + + +def d(osname, version, release): + return"{}-{}.{}".format(osname, version, release) + + +def e(): + yield"{}".format(1) + + +assert"{}".format(1) + + +async def c(): + return "{}".format(await 3) + + +async def c(): + return "{}".format(1 + await 3) + + +"{}".format(1 * 2) + ### # Non-errors ### @@ -85,8 +141,6 @@ "{} {}".format(*a) -"{0} {0}".format(arg) - "{x} {x}".format(arg) "{x.y} {x.z}".format(arg) @@ -103,8 +157,6 @@ r'"\N{snowman} {}".format(a)' -"{a}" "{b}".format(a=1, b=1) - "123456789 {}".format( 11111111111111111111111111111111111111111111111111111111111111111111111111, ) @@ -140,20 +192,13 @@ ] ) -async def c(): - return "{}".format(await 3) - - -async def c(): - return "{}".format(1 + await 3) - - -def d(osname, version, release): - return"{}-{}.{}".format(osname, version, release) - - -def e(): - yield"{}".format(1) +( + "{a}" + "{1 + 2}" +).format(a=1) +"{}".format(**c) -assert"{}".format(1) +"{}".format( + 1 # comment +) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py index a185c4867fcdd..80c0eb966f212 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py @@ -46,6 +46,35 @@ if True: from collections import ( Mapping, Counter) +# Bad imports from PYI027 that are now handled by PYI022 (UP035) +from typing import ContextManager +from typing import OrderedDict +from typing_extensions import OrderedDict +from typing import Callable +from typing import ByteString +from typing import Container +from typing import Hashable +from typing import ItemsView +from typing import Iterable +from typing import Iterator +from typing import KeysView +from typing import Mapping +from typing import MappingView +from typing import MutableMapping +from typing import MutableSequence +from typing import MutableSet +from typing import Sequence +from typing import Sized +from typing import ValuesView +from typing import Awaitable +from typing import AsyncIterator +from typing import AsyncIterable +from typing import Coroutine +from typing import Collection +from typing import AsyncGenerator +from typing import Reversible +from typing import Generator + # OK from a import b diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP040.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP040.py new file mode 100644 index 0000000000000..49fb6f7c84673 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP040.py @@ -0,0 +1,47 @@ +import typing +from typing import TypeAlias + +# UP040 +x: typing.TypeAlias = int +x: TypeAlias = int + +# UP040 simple generic +T = typing.TypeVar["T"] +x: typing.TypeAlias = list[T] + +# UP040 call style generic +T = typing.TypeVar("T") +x: typing.TypeAlias = list[T] + +# UP040 bounded generic (todo) +T = typing.TypeVar("T", bound=int) +x: typing.TypeAlias = list[T] + +T = typing.TypeVar("T", int, str) +x: typing.TypeAlias = list[T] + +# UP040 contravariant generic (todo) +T = typing.TypeVar("T", contravariant=True) +x: typing.TypeAlias = list[T] + +# UP040 covariant generic (todo) +T = typing.TypeVar("T", covariant=True) +x: typing.TypeAlias = list[T] + +# UP040 in class scope +T = typing.TypeVar["T"] +class Foo: + # reference to global variable + x: typing.TypeAlias = list[T] + + # reference to class variable + TCLS = typing.TypeVar["TCLS"] + y: typing.TypeAlias = list[TCLS] + +# UP040 wont add generics in fix +T = typing.TypeVar(*args) +x: typing.TypeAlias = list[T] + +# OK +x: TypeAlias +x: int = 1 diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF012.py b/crates/ruff/resources/test/fixtures/ruff/RUF012.py index 9be4b88c76b7d..9f7349f740ae4 100644 --- a/crates/ruff/resources/test/fixtures/ruff/RUF012.py +++ b/crates/ruff/resources/test/fixtures/ruff/RUF012.py @@ -11,6 +11,8 @@ class A: without_annotation = [] class_variable: ClassVar[list[int]] = [] final_variable: Final[list[int]] = [] + class_variable_without_subscript: ClassVar = [] + final_variable_without_subscript: Final = [] from dataclasses import dataclass, field diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF017.py b/crates/ruff/resources/test/fixtures/ruff/RUF017.py new file mode 100644 index 0000000000000..f7c062d894778 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/ruff/RUF017.py @@ -0,0 +1,14 @@ +x = [1, 2, 3] +y = [4, 5, 6] + +# RUF017 +sum([x, y], start=[]) +sum([x, y], []) +sum([[1, 2, 3], [4, 5, 6]], start=[]) +sum([[1, 2, 3], [4, 5, 6]], []) +sum([[1, 2, 3], [4, 5, 6]], + []) + +# OK +sum([x, y]) +sum([[1, 2, 3], [4, 5, 6]]) diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF100_4.py b/crates/ruff/resources/test/fixtures/ruff/RUF100_4.py new file mode 100644 index 0000000000000..51830749f5fb4 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/ruff/RUF100_4.py @@ -0,0 +1,5 @@ +# ruff: noqa: RUF100 + +import os # noqa: F401 + +print(os.sep) diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF100_5.py b/crates/ruff/resources/test/fixtures/ruff/RUF100_5.py new file mode 100644 index 0000000000000..d5d7f47b02cff --- /dev/null +++ b/crates/ruff/resources/test/fixtures/ruff/RUF100_5.py @@ -0,0 +1,11 @@ +#import os # noqa +#import os # noqa: ERA001 + +dictionary = { + # "key1": 123, # noqa: ERA001 + # "key2": 456, # noqa + # "key3": 789, +} + + +#import os # noqa: E501 diff --git a/crates/ruff/resources/test/fixtures/tryceratops/TRY003.py b/crates/ruff/resources/test/fixtures/tryceratops/TRY003.py index b6ae22682f916..5de205fa4c184 100644 --- a/crates/ruff/resources/test/fixtures/tryceratops/TRY003.py +++ b/crates/ruff/resources/test/fixtures/tryceratops/TRY003.py @@ -52,3 +52,7 @@ def good(a: int): def another_good(a): if a % 2 == 0: raise GoodArgCantBeEven(a) + + +def another_good(): + raise NotImplementedError("This is acceptable too") diff --git a/crates/ruff/src/autofix/codemods.rs b/crates/ruff/src/autofix/codemods.rs index 18f7723b3c40e..be7028d5f3ec9 100644 --- a/crates/ruff/src/autofix/codemods.rs +++ b/crates/ruff/src/autofix/codemods.rs @@ -33,7 +33,7 @@ impl<'a, T: Codegen<'a>> CodegenStylist<'a> for T { /// /// Returns `Ok(None)` if the statement is empty after removing the imports. pub(crate) fn remove_imports<'a>( - imports: impl Iterator, + member_names: impl Iterator, stmt: &Stmt, locator: &Locator, stylist: &Stylist, @@ -45,27 +45,20 @@ pub(crate) fn remove_imports<'a>( bail!("Expected Statement::Simple"); }; - let (aliases, import_module) = match body.body.first_mut() { - Some(SmallStatement::Import(import_body)) => (&mut import_body.names, None), + let aliases = match body.body.first_mut() { + Some(SmallStatement::Import(import_body)) => &mut import_body.names, Some(SmallStatement::ImportFrom(import_body)) => { if let ImportNames::Aliases(names) = &mut import_body.names { - ( - names, - Some((&import_body.relative, import_body.module.as_ref())), - ) + names } else if let ImportNames::Star(..) = &import_body.names { // Special-case: if the import is a `from ... import *`, then we delete the // entire statement. let mut found_star = false; - for import in imports { - let qualified_name = match import_body.module.as_ref() { - Some(module_name) => format!("{}.*", compose_module_path(module_name)), - None => "*".to_string(), - }; - if import == qualified_name { + for member in member_names { + if member == "*" { found_star = true; } else { - bail!("Expected \"*\" for unused import (got: \"{}\")", import); + bail!("Expected \"*\" for unused import (got: \"{}\")", member); } } if !found_star { @@ -82,30 +75,10 @@ pub(crate) fn remove_imports<'a>( // Preserve the trailing comma (or not) from the last entry. let trailing_comma = aliases.last().and_then(|alias| alias.comma.clone()); - for import in imports { - let alias_index = aliases.iter().position(|alias| { - let qualified_name = match import_module { - Some((relative, module)) => { - let module = module.map(compose_module_path); - let member = compose_module_path(&alias.name); - let mut qualified_name = String::with_capacity( - relative.len() + module.as_ref().map_or(0, String::len) + member.len() + 1, - ); - for _ in 0..relative.len() { - qualified_name.push('.'); - } - if let Some(module) = module { - qualified_name.push_str(&module); - qualified_name.push('.'); - } - qualified_name.push_str(&member); - qualified_name - } - None => compose_module_path(&alias.name), - }; - qualified_name == import - }); - + for member in member_names { + let alias_index = aliases + .iter() + .position(|alias| member == compose_module_path(&alias.name)); if let Some(index) = alias_index { aliases.remove(index); } @@ -139,7 +112,7 @@ pub(crate) fn remove_imports<'a>( /// /// Returns the modified import statement. pub(crate) fn retain_imports( - imports: &[&str], + member_names: &[&str], stmt: &Stmt, locator: &Locator, stylist: &Stylist, @@ -151,14 +124,11 @@ pub(crate) fn retain_imports( bail!("Expected Statement::Simple"); }; - let (aliases, import_module) = match body.body.first_mut() { - Some(SmallStatement::Import(import_body)) => (&mut import_body.names, None), + let aliases = match body.body.first_mut() { + Some(SmallStatement::Import(import_body)) => &mut import_body.names, Some(SmallStatement::ImportFrom(import_body)) => { if let ImportNames::Aliases(names) = &mut import_body.names { - ( - names, - Some((&import_body.relative, import_body.module.as_ref())), - ) + names } else { bail!("Expected: ImportNames::Aliases"); } @@ -170,28 +140,9 @@ pub(crate) fn retain_imports( let trailing_comma = aliases.last().and_then(|alias| alias.comma.clone()); aliases.retain(|alias| { - imports.iter().any(|import| { - let qualified_name = match import_module { - Some((relative, module)) => { - let module = module.map(compose_module_path); - let member = compose_module_path(&alias.name); - let mut qualified_name = String::with_capacity( - relative.len() + module.as_ref().map_or(0, String::len) + member.len() + 1, - ); - for _ in 0..relative.len() { - qualified_name.push('.'); - } - if let Some(module) = module { - qualified_name.push_str(&module); - qualified_name.push('.'); - } - qualified_name.push_str(&member); - qualified_name - } - None => compose_module_path(&alias.name), - }; - qualified_name == *import - }) + member_names + .iter() + .any(|member| *member == compose_module_path(&alias.name)) }); // But avoid destroying any trailing comments. diff --git a/crates/ruff/src/autofix/edits.rs b/crates/ruff/src/autofix/edits.rs index c2c02bdf30771..4f02de6c3238e 100644 --- a/crates/ruff/src/autofix/edits.rs +++ b/crates/ruff/src/autofix/edits.rs @@ -1,14 +1,17 @@ //! Interface for generating autofix edits from higher-level actions (e.g., "remove an argument"). -use anyhow::{bail, Result}; -use ruff_python_ast::{self as ast, ExceptHandler, Expr, Keyword, Ranged, Stmt}; -use ruff_python_parser::{lexer, Mode}; -use ruff_text_size::{TextLen, TextRange, TextSize}; + +use anyhow::{Context, Result}; use ruff_diagnostics::Edit; +use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Expr, Keyword, Ranged, Stmt}; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; -use ruff_python_trivia::{has_leading_content, is_python_whitespace, PythonWhitespace}; + +use ruff_python_trivia::{ + has_leading_content, is_python_whitespace, PythonWhitespace, SimpleTokenKind, SimpleTokenizer, +}; use ruff_source_file::{Locator, NewlineWithTrailingNewline}; +use ruff_text_size::{TextLen, TextSize}; use crate::autofix::codemods; @@ -45,7 +48,7 @@ pub(crate) fn delete_stmt( } else if has_leading_content(stmt.start(), locator) { Edit::range_deletion(stmt.range()) } else if let Some(start) = indexer.preceded_by_continuations(stmt.start(), locator) { - Edit::range_deletion(TextRange::new(start, stmt.end())) + Edit::deletion(start, stmt.end()) } else { let range = locator.full_lines_range(stmt.range()); Edit::range_deletion(range) @@ -55,118 +58,84 @@ pub(crate) fn delete_stmt( /// Generate a `Fix` to remove the specified imports from an `import` statement. pub(crate) fn remove_unused_imports<'a>( - unused_imports: impl Iterator, + member_names: impl Iterator, stmt: &Stmt, parent: Option<&Stmt>, locator: &Locator, stylist: &Stylist, indexer: &Indexer, ) -> Result { - match codemods::remove_imports(unused_imports, stmt, locator, stylist)? { + match codemods::remove_imports(member_names, stmt, locator, stylist)? { None => Ok(delete_stmt(stmt, parent, locator, indexer)), Some(content) => Ok(Edit::range_replacement(content, stmt.range())), } } +#[derive(Debug, Copy, Clone)] +pub(crate) enum Parentheses { + /// Remove parentheses, if the removed argument is the only argument left. + Remove, + /// Preserve parentheses, even if the removed argument is the only argument + Preserve, +} + /// Generic function to remove arguments or keyword arguments in function /// calls and class definitions. (For classes `args` should be considered /// `bases`) /// /// Supports the removal of parentheses when this is the only (kw)arg left. /// For this behavior, set `remove_parentheses` to `true`. -pub(crate) fn remove_argument( - locator: &Locator, - call_at: TextSize, - expr_range: TextRange, - args: &[Expr], - keywords: &[Keyword], - remove_parentheses: bool, +pub(crate) fn remove_argument( + argument: &T, + arguments: &Arguments, + parentheses: Parentheses, + source: &str, ) -> Result { - // TODO(sbrugman): Preserve trailing comments. - let contents = locator.after(call_at); + // Partition into arguments before and after the argument to remove. + let (before, after): (Vec<_>, Vec<_>) = arguments + .args + .iter() + .map(Expr::range) + .chain(arguments.keywords.iter().map(Keyword::range)) + .filter(|range| argument.range() != *range) + .partition(|range| range.start() < argument.start()); - let mut fix_start = None; - let mut fix_end = None; + if !after.is_empty() { + // Case 1: argument or keyword is _not_ the last node, so delete from the start of the + // argument to the end of the subsequent comma. + let mut tokenizer = SimpleTokenizer::starts_at(argument.end(), source); - let n_arguments = keywords.len() + args.len(); - if n_arguments == 0 { - bail!("No arguments or keywords to remove"); - } + // Find the trailing comma. + tokenizer + .find(|token| token.kind == SimpleTokenKind::Comma) + .context("Unable to find trailing comma")?; - if n_arguments == 1 { - // Case 1: there is only one argument. - let mut count = 0u32; - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() { - if tok.is_lpar() { - if count == 0 { - fix_start = Some(if remove_parentheses { - range.start() - } else { - range.start() + TextSize::from(1) - }); - } - count = count.saturating_add(1); - } + // Find the next non-whitespace token. + let next = tokenizer + .find(|token| { + token.kind != SimpleTokenKind::Whitespace && token.kind != SimpleTokenKind::Newline + }) + .context("Unable to find next token")?; - if tok.is_rpar() { - count = count.saturating_sub(1); - if count == 0 { - fix_end = Some(if remove_parentheses { - range.end() - } else { - range.end() - TextSize::from(1) - }); - break; - } - } - } - } else if args - .iter() - .map(Expr::start) - .chain(keywords.iter().map(Keyword::start)) - .any(|location| location > expr_range.start()) - { - // Case 2: argument or keyword is _not_ the last node. - let mut seen_comma = false; - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() { - if seen_comma { - if tok.is_non_logical_newline() { - // Also delete any non-logical newlines after the comma. - continue; - } - fix_end = Some(if tok.is_newline() { - range.end() - } else { - range.start() - }); - break; - } - if range.start() == expr_range.start() { - fix_start = Some(range.start()); - } - if fix_start.is_some() && tok.is_comma() { - seen_comma = true; - } - } - } else { - // Case 3: argument or keyword is the last node, so we have to find the last - // comma in the stmt. - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() { - if range.start() == expr_range.start() { - fix_end = Some(expr_range.end()); - break; - } - if tok.is_comma() { - fix_start = Some(range.start()); - } - } - } + Ok(Edit::deletion(argument.start(), next.start())) + } else if let Some(previous) = before.iter().map(Ranged::end).max() { + // Case 2: argument or keyword is the last node, so delete from the start of the + // previous comma to the end of the argument. + let mut tokenizer = SimpleTokenizer::starts_at(previous, source); - match (fix_start, fix_end) { - (Some(start), Some(end)) => Ok(Edit::deletion(start, end)), - _ => { - bail!("No fix could be constructed") - } + // Find the trailing comma. + let comma = tokenizer + .find(|token| token.kind == SimpleTokenKind::Comma) + .context("Unable to find trailing comma")?; + + Ok(Edit::deletion(comma.start(), argument.end())) + } else { + // Case 3: argument or keyword is the only node, so delete the arguments (but preserve + // parentheses, if needed). + Ok(match parentheses { + Parentheses::Remove => Edit::range_deletion(arguments.range()), + Parentheses::Preserve => Edit::range_replacement("()".to_string(), arguments.range()), + }) } } @@ -179,16 +148,13 @@ fn is_only(vec: &[T], value: &T) -> bool { fn is_lone_child(child: &Stmt, parent: &Stmt) -> bool { match parent { Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) | Stmt::ClassDef(ast::StmtClassDef { body, .. }) - | Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + | Stmt::With(ast::StmtWith { body, .. }) => { if is_only(body, child) { return true; } } Stmt::For(ast::StmtFor { body, orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) | Stmt::While(ast::StmtWhile { body, orelse, .. }) => { if is_only(body, child) || is_only(orelse, child) { return true; @@ -212,14 +178,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt) -> bool { handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { if is_only(body, child) || is_only(orelse, child) @@ -267,25 +226,25 @@ fn trailing_semicolon(offset: TextSize, locator: &Locator) -> Option { fn next_stmt_break(semicolon: TextSize, locator: &Locator) -> TextSize { let start_location = semicolon + TextSize::from(1); - let contents = &locator.contents()[usize::from(start_location)..]; - for line in NewlineWithTrailingNewline::from(contents) { + for line in + NewlineWithTrailingNewline::with_offset(locator.after(start_location), start_location) + { let trimmed = line.trim_whitespace(); // Skip past any continuations. if trimmed.starts_with('\\') { continue; } - return start_location - + if trimmed.is_empty() { - // If the line is empty, then despite the previous statement ending in a - // semicolon, we know that it's not a multi-statement line. - line.start() - } else { - // Otherwise, find the start of the next statement. (Or, anything that isn't - // whitespace.) - let relative_offset = line.find(|c: char| !is_python_whitespace(c)).unwrap(); - line.start() + TextSize::try_from(relative_offset).unwrap() - }; + return if trimmed.is_empty() { + // If the line is empty, then despite the previous statement ending in a + // semicolon, we know that it's not a multi-statement line. + line.start() + } else { + // Otherwise, find the start of the next statement. (Or, anything that isn't + // whitespace.) + let relative_offset = line.find(|c: char| !is_python_whitespace(c)).unwrap(); + line.start() + TextSize::try_from(relative_offset).unwrap() + }; } locator.line_end(start_location) @@ -294,24 +253,24 @@ fn next_stmt_break(semicolon: TextSize, locator: &Locator) -> TextSize { #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::{Ranged, Suite}; - use ruff_python_parser::Parse; - use ruff_text_size::TextSize; + use ruff_python_ast::Ranged; + use ruff_python_parser::parse_suite; use ruff_source_file::Locator; + use ruff_text_size::TextSize; use crate::autofix::edits::{next_stmt_break, trailing_semicolon}; #[test] fn find_semicolon() -> Result<()> { let contents = "x = 1"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert_eq!(trailing_semicolon(stmt.end(), &locator), None); let contents = "x = 1; y = 1"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert_eq!( @@ -320,7 +279,7 @@ mod tests { ); let contents = "x = 1 ; y = 1"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert_eq!( @@ -333,7 +292,7 @@ x = 1 \ ; y = 1 " .trim(); - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert_eq!( diff --git a/crates/ruff/src/autofix/mod.rs b/crates/ruff/src/autofix/mod.rs index ab7b85f56d57d..358a693cc0bcb 100644 --- a/crates/ruff/src/autofix/mod.rs +++ b/crates/ruff/src/autofix/mod.rs @@ -13,6 +13,7 @@ use crate::registry::{AsRule, Rule}; pub(crate) mod codemods; pub(crate) mod edits; +pub(crate) mod snippet; pub(crate) mod source_map; pub(crate) struct FixResult { @@ -76,7 +77,7 @@ fn apply_fixes<'a>( } // If this fix overlaps with a fix we've already applied, skip it. - if last_pos.map_or(false, |last_pos| last_pos >= first.start()) { + if last_pos.is_some_and(|last_pos| last_pos >= first.start()) { continue; } } diff --git a/crates/ruff/src/autofix/snippet.rs b/crates/ruff/src/autofix/snippet.rs new file mode 100644 index 0000000000000..5d83b87de97c2 --- /dev/null +++ b/crates/ruff/src/autofix/snippet.rs @@ -0,0 +1,36 @@ +use unicode_width::UnicodeWidthStr; + +/// A snippet of source code for user-facing display, as in a diagnostic. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct SourceCodeSnippet(String); + +impl SourceCodeSnippet { + pub(crate) fn new(source_code: String) -> Self { + Self(source_code) + } + + /// Return the full snippet for user-facing display, or `None` if the snippet should be + /// truncated. + pub(crate) fn full_display(&self) -> Option<&str> { + if Self::should_truncate(&self.0) { + None + } else { + Some(&self.0) + } + } + + /// Return a truncated snippet for user-facing display. + pub(crate) fn truncated_display(&self) -> &str { + if Self::should_truncate(&self.0) { + "..." + } else { + &self.0 + } + } + + /// Returns `true` if the source code should be truncated when included in a user-facing + /// diagnostic. + fn should_truncate(source_code: &str) -> bool { + source_code.width() > 50 || source_code.contains(['\r', '\n']) + } +} diff --git a/crates/ruff/src/checkers/ast/analyze/bindings.rs b/crates/ruff/src/checkers/ast/analyze/bindings.rs index 80c632308fbea..face2218220c7 100644 --- a/crates/ruff/src/checkers/ast/analyze/bindings.rs +++ b/crates/ruff/src/checkers/ast/analyze/bindings.rs @@ -1,4 +1,5 @@ use ruff_diagnostics::{Diagnostic, Fix}; +use ruff_python_ast::Ranged; use crate::checkers::ast::Checker; use crate::codes::Rule; @@ -16,14 +17,20 @@ pub(crate) fn bindings(checker: &mut Checker) { return; } - for binding in checker.semantic.bindings.iter() { + for binding in &*checker.semantic.bindings { if checker.enabled(Rule::UnusedVariable) { - if binding.kind.is_bound_exception() && !binding.is_used() { + if binding.kind.is_bound_exception() + && !binding.is_used() + && !checker + .settings + .dummy_variable_rgx + .is_match(binding.name(checker.locator)) + { let mut diagnostic = Diagnostic::new( pyflakes::rules::UnusedVariable { name: binding.name(checker.locator).to_string(), }, - binding.range, + binding.range(), ); if checker.patch(Rule::UnusedVariable) { diagnostic.try_set_fix(|| { @@ -56,13 +63,11 @@ pub(crate) fn bindings(checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } - if checker.is_stub { - if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) { - if let Some(diagnostic) = - flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding) - { - checker.diagnostics.push(diagnostic); - } + if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) { + if let Some(diagnostic) = + flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding) + { + checker.diagnostics.push(diagnostic); } } } diff --git a/crates/ruff/src/checkers/ast/analyze/comprehension.rs b/crates/ruff/src/checkers/ast/analyze/comprehension.rs index 8cd73dca0e4ea..c3d368be2954a 100644 --- a/crates/ruff/src/checkers/ast/analyze/comprehension.rs +++ b/crates/ruff/src/checkers/ast/analyze/comprehension.rs @@ -7,10 +7,6 @@ use crate::rules::flake8_simplify; /// Run lint rules over a [`Comprehension`] syntax nodes. pub(crate) fn comprehension(comprehension: &Comprehension, checker: &mut Checker) { if checker.enabled(Rule::InDictKeys) { - flake8_simplify::rules::key_in_dict_for( - checker, - &comprehension.target, - &comprehension.iter, - ); + flake8_simplify::rules::key_in_dict_comprehension(checker, comprehension); } } diff --git a/crates/ruff/src/checkers/ast/analyze/deferred_for_loops.rs b/crates/ruff/src/checkers/ast/analyze/deferred_for_loops.rs index ebacfc477825d..bb1805ba7790e 100644 --- a/crates/ruff/src/checkers/ast/analyze/deferred_for_loops.rs +++ b/crates/ruff/src/checkers/ast/analyze/deferred_for_loops.rs @@ -1,8 +1,8 @@ -use ruff_python_ast::{self as ast, Stmt}; +use ruff_python_ast::Stmt; use crate::checkers::ast::Checker; use crate::codes::Rule; -use crate::rules::{flake8_bugbear, perflint}; +use crate::rules::{flake8_bugbear, perflint, pyupgrade}; /// Run lint rules over all deferred for-loops in the [`SemanticModel`]. pub(crate) fn deferred_for_loops(checker: &mut Checker) { @@ -11,21 +11,18 @@ pub(crate) fn deferred_for_loops(checker: &mut Checker) { for snapshot in for_loops { checker.semantic.restore(snapshot); - if let Stmt::For(ast::StmtFor { - target, iter, body, .. - }) - | Stmt::AsyncFor(ast::StmtAsyncFor { - target, iter, body, .. - }) = &checker.semantic.stmt() - { - if checker.enabled(Rule::UnusedLoopControlVariable) { - flake8_bugbear::rules::unused_loop_control_variable(checker, target, body); - } - if checker.enabled(Rule::IncorrectDictIterator) { - perflint::rules::incorrect_dict_iterator(checker, target, iter); - } - } else { - unreachable!("Expected Expr::For | Expr::AsyncFor"); + let Stmt::For(stmt_for) = checker.semantic.current_statement() else { + unreachable!("Expected Stmt::For"); + }; + + if checker.enabled(Rule::UnusedLoopControlVariable) { + flake8_bugbear::rules::unused_loop_control_variable(checker, stmt_for); + } + if checker.enabled(Rule::IncorrectDictIterator) { + perflint::rules::incorrect_dict_iterator(checker, stmt_for); + } + if checker.enabled(Rule::YieldInForLoop) { + pyupgrade::rules::yield_in_for_loop(checker, stmt_for); } } } diff --git a/crates/ruff/src/checkers/ast/analyze/deferred_scopes.rs b/crates/ruff/src/checkers/ast/analyze/deferred_scopes.rs index f020fcadbb674..32bea594b9272 100644 --- a/crates/ruff/src/checkers/ast/analyze/deferred_scopes.rs +++ b/crates/ruff/src/checkers/ast/analyze/deferred_scopes.rs @@ -1,6 +1,6 @@ use ruff_diagnostics::Diagnostic; -use ruff_python_ast::cast; -use ruff_python_semantic::analyze::{branch_detection, visibility}; +use ruff_python_ast::Ranged; +use ruff_python_semantic::analyze::visibility; use ruff_python_semantic::{Binding, BindingKind, ScopeKind}; use crate::checkers::ast::Checker; @@ -30,6 +30,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { Rule::UnusedPrivateTypedDict, Rule::UnusedStaticMethodArgument, Rule::UnusedVariable, + Rule::NoSelfUse, ]) { return; } @@ -37,7 +38,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { // Identify any valid runtime imports. If a module is imported at runtime, and // used at runtime, then by default, we avoid flagging any other // imports from that model as typing-only. - let enforce_typing_imports = !checker.is_stub + let enforce_typing_imports = !checker.source_type.is_stub() && checker.any_enabled(&[ Rule::RuntimeImportInTypeCheckingBlock, Rule::TypingOnlyFirstPartyImport, @@ -82,7 +83,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { pylint::rules::GlobalVariableNotAssigned { name: (*name).to_string(), }, - binding.range, + binding.range(), )); } } @@ -112,21 +113,21 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { // If the bindings are in different forks, abort. if shadowed.source.map_or(true, |left| { binding.source.map_or(true, |right| { - branch_detection::different_forks(left, right, &checker.semantic.stmts) + checker.semantic.different_branches(left, right) }) }) { continue; } #[allow(deprecated)] - let line = checker.locator.compute_line_index(shadowed.range.start()); + let line = checker.locator.compute_line_index(shadowed.start()); checker.diagnostics.push(Diagnostic::new( pyflakes::rules::ImportShadowedByLoopVar { name: name.to_string(), line, }, - binding.range, + binding.range(), )); } } @@ -168,16 +169,25 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { continue; } - // If this is an overloaded function, abort. - if shadowed.kind.is_function_definition() - && visibility::is_overload( - cast::decorator_list( - checker.semantic.stmts[shadowed.source.unwrap()], - ), - &checker.semantic, - ) - { + let Some(node_id) = shadowed.source else { continue; + }; + + // If this is an overloaded function, abort. + if shadowed.kind.is_function_definition() { + if checker + .semantic + .statement(node_id) + .as_function_def_stmt() + .is_some_and(|function| { + visibility::is_overload( + &function.decorator_list, + &checker.semantic, + ) + }) + { + continue; + } } } else { // Only enforce cross-scope shadowing for imports. @@ -195,20 +205,20 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { // If the bindings are in different forks, abort. if shadowed.source.map_or(true, |left| { binding.source.map_or(true, |right| { - branch_detection::different_forks(left, right, &checker.semantic.stmts) + checker.semantic.different_branches(left, right) }) }) { continue; } #[allow(deprecated)] - let line = checker.locator.compute_line_index(shadowed.range.start()); + let line = checker.locator.compute_line_index(shadowed.start()); let mut diagnostic = Diagnostic::new( pyflakes::rules::RedefinedWhileUnused { name: (*name).to_string(), line, }, - binding.range, + binding.range(), ); if let Some(range) = binding.parent_range(&checker.semantic) { diagnostic.set_parent(range.start()); @@ -218,25 +228,20 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { } } - if checker.is_stub { - if checker.enabled(Rule::UnusedPrivateTypeVar) { - flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics); - } - if checker.enabled(Rule::UnusedPrivateProtocol) { - flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics); - } - if checker.enabled(Rule::UnusedPrivateTypeAlias) { - flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics); - } - if checker.enabled(Rule::UnusedPrivateTypedDict) { - flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics); - } + if checker.enabled(Rule::UnusedPrivateTypeVar) { + flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics); + } + if checker.enabled(Rule::UnusedPrivateProtocol) { + flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics); + } + if checker.enabled(Rule::UnusedPrivateTypeAlias) { + flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics); + } + if checker.enabled(Rule::UnusedPrivateTypedDict) { + flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics); } - if matches!( - scope.kind, - ScopeKind::Function(_) | ScopeKind::AsyncFunction(_) | ScopeKind::Lambda(_) - ) { + if matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Lambda(_)) { if checker.enabled(Rule::UnusedVariable) { pyflakes::rules::unused_variable(checker, scope, &mut diagnostics); } @@ -245,7 +250,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { pyflakes::rules::unused_annotation(checker, scope, &mut diagnostics); } - if !checker.is_stub { + if !checker.source_type.is_stub() { if checker.any_enabled(&[ Rule::UnusedClassMethodArgument, Rule::UnusedFunctionArgument, @@ -262,10 +267,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { } } - if matches!( - scope.kind, - ScopeKind::Function(_) | ScopeKind::AsyncFunction(_) | ScopeKind::Module - ) { + if matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Module) { if enforce_typing_imports { let runtime_imports: Vec<&Binding> = checker .semantic @@ -301,6 +303,12 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) { pyflakes::rules::unused_import(checker, scope, &mut diagnostics); } } + + if scope.kind.is_function() { + if checker.enabled(Rule::NoSelfUse) { + pylint::rules::no_self_use(checker, scope, &mut diagnostics); + } + } } checker.diagnostics.extend(diagnostics); } diff --git a/crates/ruff/src/checkers/ast/analyze/definitions.rs b/crates/ruff/src/checkers/ast/analyze/definitions.rs index d46e261413910..a6d86cad5d7db 100644 --- a/crates/ruff/src/checkers/ast/analyze/definitions.rs +++ b/crates/ruff/src/checkers/ast/analyze/definitions.rs @@ -30,8 +30,8 @@ pub(crate) fn definitions(checker: &mut Checker) { Rule::MissingTypeKwargs, Rule::MissingTypeSelf, ]); - let enforce_stubs = checker.is_stub - && checker.any_enabled(&[Rule::DocstringInStub, Rule::IterMethodReturnIterable]); + let enforce_stubs = checker.source_type.is_stub() && checker.enabled(Rule::DocstringInStub); + let enforce_stubs_and_runtime = checker.enabled(Rule::IterMethodReturnIterable); let enforce_docstrings = checker.any_enabled(&[ Rule::BlankLineAfterLastSection, Rule::BlankLineAfterSummary, @@ -81,7 +81,7 @@ pub(crate) fn definitions(checker: &mut Checker) { Rule::UndocumentedPublicPackage, ]); - if !enforce_annotations && !enforce_docstrings && !enforce_stubs { + if !enforce_annotations && !enforce_docstrings && !enforce_stubs && !enforce_stubs_and_runtime { return; } @@ -117,7 +117,7 @@ pub(crate) fn definitions(checker: &mut Checker) { // interfaces, without any AST nodes in between. Right now, we // only error when traversing definition boundaries (functions, // classes, etc.). - if !overloaded_name.map_or(false, |overloaded_name| { + if !overloaded_name.is_some_and(|overloaded_name| { flake8_annotations::helpers::is_overload_impl( definition, &overloaded_name, @@ -141,6 +141,8 @@ pub(crate) fn definitions(checker: &mut Checker) { if checker.enabled(Rule::DocstringInStub) { flake8_pyi::rules::docstring_in_stubs(checker, docstring); } + } + if enforce_stubs_and_runtime { if checker.enabled(Rule::IterMethodReturnIterable) { flake8_pyi::rules::iter_method_return_iterable(checker, definition); } @@ -169,7 +171,7 @@ pub(crate) fn definitions(checker: &mut Checker) { expr.start(), )); - if pydocstyle::helpers::should_ignore_docstring(contents) { + if pydocstyle::helpers::should_ignore_docstring(expr) { #[allow(deprecated)] let location = checker.locator.compute_source_location(expr.start()); warn_user!( diff --git a/crates/ruff/src/checkers/ast/analyze/expression.rs b/crates/ruff/src/checkers/ast/analyze/expression.rs index fb4501fe45f5d..20352a1067f51 100644 --- a/crates/ruff/src/checkers/ast/analyze/expression.rs +++ b/crates/ruff/src/checkers/ast/analyze/expression.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, ExprContext, Operator, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, ExprContext, Operator, Ranged}; use ruff_python_literal::cformat::{CFormatError, CFormatErrorType}; use ruff_diagnostics::Diagnostic; @@ -31,7 +31,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { if let Some(operator) = typing::to_pep604_operator(value, slice, &checker.semantic) { if checker.enabled(Rule::FutureRewritableTypeAnnotation) { - if !checker.is_stub + if !checker.source_type.is_stub() && checker.settings.target_version < PythonVersion::Py310 && checker.settings.target_version >= PythonVersion::Py37 && !checker.semantic.future_annotations() @@ -44,7 +44,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } } if checker.enabled(Rule::NonPEP604Annotation) { - if checker.is_stub + if checker.source_type.is_stub() || checker.settings.target_version >= PythonVersion::Py310 || (checker.settings.target_version >= PythonVersion::Py37 && checker.semantic.future_annotations() @@ -59,7 +59,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { // Ex) list[...] if checker.enabled(Rule::FutureRequiredTypeAnnotation) { - if !checker.is_stub + if !checker.source_type.is_stub() && checker.settings.target_version < PythonVersion::Py39 && !checker.semantic.future_annotations() && checker.semantic.in_annotation() @@ -74,24 +74,27 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } // Ex) Union[...] - if checker.any_enabled(&[Rule::UnnecessaryLiteralUnion, Rule::DuplicateUnionMember]) { - // Determine if the current expression is an union - // Avoid duplicate checks if the parent is an `Union[...]` since these rules traverse nested unions - let is_unchecked_union = checker - .semantic - .expr_grandparent() - .and_then(Expr::as_subscript_expr) - .map_or(true, |parent| { - !checker.semantic.match_typing_expr(&parent.value, "Union") - }); - - if is_unchecked_union { + if checker.any_enabled(&[ + Rule::UnnecessaryLiteralUnion, + Rule::DuplicateUnionMember, + Rule::RedundantLiteralUnion, + Rule::UnnecessaryTypeUnion, + ]) { + // Avoid duplicate checks if the parent is a union, since these rules already + // traverse nested unions. + if !checker.semantic.in_nested_union() { if checker.enabled(Rule::UnnecessaryLiteralUnion) { flake8_pyi::rules::unnecessary_literal_union(checker, expr); } if checker.enabled(Rule::DuplicateUnionMember) { flake8_pyi::rules::duplicate_union_member(checker, expr); } + if checker.enabled(Rule::RedundantLiteralUnion) { + flake8_pyi::rules::redundant_literal_union(checker, expr); + } + if checker.enabled(Rule::UnnecessaryTypeUnion) { + flake8_pyi::rules::unnecessary_type_union(checker, expr); + } } } @@ -152,10 +155,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { if checker.enabled(Rule::NumpyDeprecatedFunction) { numpy::rules::deprecated_function(checker, expr); } - if checker.is_stub { - if checker.enabled(Rule::CollectionsNamedTuple) { - flake8_pyi::rules::collections_named_tuple(checker, expr); - } + if checker.enabled(Rule::CollectionsNamedTuple) { + flake8_pyi::rules::collections_named_tuple(checker, expr); } // Ex) List[...] @@ -167,20 +168,18 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { typing::to_pep585_generic(expr, &checker.semantic) { if checker.enabled(Rule::FutureRewritableTypeAnnotation) { - if !checker.is_stub + if !checker.source_type.is_stub() && checker.settings.target_version < PythonVersion::Py39 && checker.settings.target_version >= PythonVersion::Py37 && !checker.semantic.future_annotations() && checker.semantic.in_annotation() && !checker.settings.pyupgrade.keep_runtime_typing { - flake8_future_annotations::rules::future_rewritable_type_annotation( - checker, expr, - ); + flake8_future_annotations::rules::future_rewritable_type_annotation(checker, expr); } } if checker.enabled(Rule::NonPEP585Annotation) { - if checker.is_stub + if checker.source_type.is_stub() || checker.settings.target_version >= PythonVersion::Py39 || (checker.settings.target_version >= PythonVersion::Py37 && checker.semantic.future_annotations() @@ -199,13 +198,13 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } ExprContext::Store => { if checker.enabled(Rule::NonLowercaseVariableInFunction) { - if checker.semantic.scope().kind.is_any_function() { + if checker.semantic.current_scope().kind.is_function() { // Ignore globals. if !checker .semantic - .scope() + .current_scope() .get(id) - .map_or(false, |binding_id| { + .is_some_and(|binding_id| { checker.semantic.binding(binding_id).is_global() }) { @@ -216,16 +215,19 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } } if checker.enabled(Rule::MixedCaseVariableInClassScope) { - if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = - &checker.semantic.scope().kind + if let ScopeKind::Class(ast::StmtClassDef { arguments, .. }) = + &checker.semantic.current_scope().kind { pep8_naming::rules::mixed_case_variable_in_class_scope( - checker, expr, id, bases, + checker, + expr, + id, + arguments.as_deref(), ); } } if checker.enabled(Rule::MixedCaseVariableInGlobalScope) { - if matches!(checker.semantic.scope().kind, ScopeKind::Module) { + if matches!(checker.semantic.current_scope().kind, ScopeKind::Module) { pep8_naming::rules::mixed_case_variable_in_global_scope( checker, expr, id, ); @@ -238,7 +240,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } - if let ScopeKind::Class(class_def) = checker.semantic.scope().kind { + if let ScopeKind::Class(class_def) = checker.semantic.current_scope().kind { if checker.enabled(Rule::BuiltinAttributeShadowing) { flake8_builtins::rules::builtin_attribute_shadowing( checker, class_def, id, *range, @@ -259,7 +261,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pylint::rules::load_before_global_declaration(checker, id, expr); } } - Expr::Attribute(ast::ExprAttribute { attr, value, .. }) => { + Expr::Attribute(attribute) => { // Ex) typing.List[...] if checker.any_enabled(&[ Rule::FutureRewritableTypeAnnotation, @@ -267,7 +269,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { ]) { if let Some(replacement) = typing::to_pep585_generic(expr, &checker.semantic) { if checker.enabled(Rule::FutureRewritableTypeAnnotation) { - if !checker.is_stub + if !checker.source_type.is_stub() && checker.settings.target_version < PythonVersion::Py39 && checker.settings.target_version >= PythonVersion::Py37 && !checker.semantic.future_annotations() @@ -280,7 +282,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } } if checker.enabled(Rule::NonPEP585Annotation) { - if checker.is_stub + if checker.source_type.is_stub() || checker.settings.target_version >= PythonVersion::Py39 || (checker.settings.target_version >= PythonVersion::Py37 && checker.semantic.future_annotations() @@ -318,22 +320,26 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { if checker.enabled(Rule::PrivateMemberAccess) { flake8_self::rules::private_member_access(checker, expr); } - if checker.is_stub { - if checker.enabled(Rule::CollectionsNamedTuple) { - flake8_pyi::rules::collections_named_tuple(checker, expr); - } + if checker.enabled(Rule::CollectionsNamedTuple) { + flake8_pyi::rules::collections_named_tuple(checker, expr); } - pandas_vet::rules::attr(checker, attr, value, expr); + pandas_vet::rules::attr(checker, attribute); } Expr::Call( call @ ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }, ) => { if checker.any_enabled(&[ + // pylint + Rule::BadStringFormatCharacter, // pyflakes Rule::StringDotFormatInvalidFormat, Rule::StringDotFormatExtraNamedArguments, @@ -375,41 +381,46 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { Ok(summary) => { if checker.enabled(Rule::StringDotFormatExtraNamedArguments) { pyflakes::rules::string_dot_format_extra_named_arguments( - checker, &summary, keywords, location, + checker, call, &summary, keywords, ); } if checker .enabled(Rule::StringDotFormatExtraPositionalArguments) { pyflakes::rules::string_dot_format_extra_positional_arguments( - checker, - &summary, args, location, - ); + checker, call, &summary, args, + ); } if checker.enabled(Rule::StringDotFormatMissingArguments) { pyflakes::rules::string_dot_format_missing_argument( - checker, &summary, args, keywords, location, + checker, call, &summary, args, keywords, ); } if checker.enabled(Rule::StringDotFormatMixingAutomatic) { pyflakes::rules::string_dot_format_mixing_automatic( - checker, &summary, location, + checker, call, &summary, ); } if checker.enabled(Rule::FormatLiterals) { - pyupgrade::rules::format_literals(checker, &summary, expr); + pyupgrade::rules::format_literals(checker, call, &summary); } if checker.enabled(Rule::FString) { pyupgrade::rules::f_strings( checker, + call, &summary, - expr, value, checker.settings.line_length, ); } } } + + if checker.enabled(Rule::BadStringFormatCharacter) { + pylint::rules::bad_string_format_character::call( + checker, val, location, + ); + } } } } @@ -421,25 +432,29 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pyupgrade::rules::deprecated_unittest_alias(checker, func); } if checker.enabled(Rule::SuperCallWithParameters) { - pyupgrade::rules::super_call_with_parameters(checker, expr, func, args); + pyupgrade::rules::super_call_with_parameters(checker, call); } if checker.enabled(Rule::UnnecessaryEncodeUTF8) { - pyupgrade::rules::unnecessary_encode_utf8(checker, expr, func, args, keywords); + pyupgrade::rules::unnecessary_encode_utf8(checker, call); } if checker.enabled(Rule::RedundantOpenModes) { - pyupgrade::rules::redundant_open_modes(checker, expr); + pyupgrade::rules::redundant_open_modes(checker, call); } if checker.enabled(Rule::NativeLiterals) { - pyupgrade::rules::native_literals(checker, expr, func, args, keywords); + pyupgrade::rules::native_literals( + checker, + call, + checker.semantic().current_expression_parent(), + ); } if checker.enabled(Rule::OpenAlias) { pyupgrade::rules::open_alias(checker, expr, func); } if checker.enabled(Rule::ReplaceUniversalNewlines) { - pyupgrade::rules::replace_universal_newlines(checker, func, keywords); + pyupgrade::rules::replace_universal_newlines(checker, call); } if checker.enabled(Rule::ReplaceStdoutStderr) { - pyupgrade::rules::replace_stdout_stderr(checker, expr, func, args, keywords); + pyupgrade::rules::replace_stdout_stderr(checker, call); } if checker.enabled(Rule::OSErrorAlias) { pyupgrade::rules::os_error_alias_call(checker, func); @@ -459,7 +474,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { flake8_async::rules::blocking_os_call(checker, expr); } if checker.any_enabled(&[Rule::Print, Rule::PPrint]) { - flake8_print::rules::print_call(checker, func, keywords); + flake8_print::rules::print_call(checker, call); } if checker.any_enabled(&[ Rule::SuspiciousPickleUsage, @@ -511,37 +526,38 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } if checker.enabled(Rule::ZipWithoutExplicitStrict) { if checker.settings.target_version >= PythonVersion::Py310 { - flake8_bugbear::rules::zip_without_explicit_strict( - checker, expr, func, args, keywords, - ); + flake8_bugbear::rules::zip_without_explicit_strict(checker, call); } } if checker.enabled(Rule::NoExplicitStacklevel) { - flake8_bugbear::rules::no_explicit_stacklevel(checker, func, keywords); + flake8_bugbear::rules::no_explicit_stacklevel(checker, call); } if checker.enabled(Rule::UnnecessaryDictKwargs) { flake8_pie::rules::unnecessary_dict_kwargs(checker, expr, keywords); } + if checker.enabled(Rule::UnnecessaryRangeStart) { + flake8_pie::rules::unnecessary_range_start(checker, call); + } if checker.enabled(Rule::ExecBuiltin) { flake8_bandit::rules::exec_used(checker, func); } if checker.enabled(Rule::BadFilePermissions) { - flake8_bandit::rules::bad_file_permissions(checker, func, args, keywords); + flake8_bandit::rules::bad_file_permissions(checker, call); } if checker.enabled(Rule::RequestWithNoCertValidation) { - flake8_bandit::rules::request_with_no_cert_validation(checker, func, keywords); + flake8_bandit::rules::request_with_no_cert_validation(checker, call); } if checker.enabled(Rule::UnsafeYAMLLoad) { - flake8_bandit::rules::unsafe_yaml_load(checker, func, args, keywords); + flake8_bandit::rules::unsafe_yaml_load(checker, call); } if checker.enabled(Rule::SnmpInsecureVersion) { - flake8_bandit::rules::snmp_insecure_version(checker, func, keywords); + flake8_bandit::rules::snmp_insecure_version(checker, call); } if checker.enabled(Rule::SnmpWeakCryptography) { - flake8_bandit::rules::snmp_weak_cryptography(checker, func, args, keywords); + flake8_bandit::rules::snmp_weak_cryptography(checker, call); } if checker.enabled(Rule::Jinja2AutoescapeFalse) { - flake8_bandit::rules::jinja2_autoescape_false(checker, func, keywords); + flake8_bandit::rules::jinja2_autoescape_false(checker, call); } if checker.enabled(Rule::HardcodedPasswordFuncArg) { flake8_bandit::rules::hardcoded_password_func_arg(checker, keywords); @@ -550,18 +566,16 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { flake8_bandit::rules::hardcoded_sql_expression(checker, expr); } if checker.enabled(Rule::HashlibInsecureHashFunction) { - flake8_bandit::rules::hashlib_insecure_hash_functions( - checker, func, args, keywords, - ); + flake8_bandit::rules::hashlib_insecure_hash_functions(checker, call); } if checker.enabled(Rule::RequestWithoutTimeout) { - flake8_bandit::rules::request_without_timeout(checker, func, keywords); + flake8_bandit::rules::request_without_timeout(checker, call); } if checker.enabled(Rule::ParamikoCall) { flake8_bandit::rules::paramiko_call(checker, func); } if checker.enabled(Rule::LoggingConfigInsecureListen) { - flake8_bandit::rules::logging_config_insecure_listen(checker, func, keywords); + flake8_bandit::rules::logging_config_insecure_listen(checker, call); } if checker.any_enabled(&[ Rule::SubprocessWithoutShellEqualsTrue, @@ -572,7 +586,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { Rule::StartProcessWithPartialPath, Rule::UnixCommandWildcardInjection, ]) { - flake8_bandit::rules::shell_injection(checker, func, args, keywords); + flake8_bandit::rules::shell_injection(checker, call); } if checker.enabled(Rule::UnnecessaryGeneratorList) { flake8_comprehensions::rules::unnecessary_generator_list( @@ -656,7 +670,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { flake8_comprehensions::rules::unnecessary_map( checker, expr, - checker.semantic.expr_parent(), + checker.semantic.current_expression_parent(), func, args, ); @@ -666,32 +680,24 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { checker, expr, func, args, keywords, ); } - if checker.enabled(Rule::BooleanPositionalValueInFunctionCall) { - flake8_boolean_trap::rules::check_boolean_positional_value_in_function_call( - checker, args, func, - ); + if checker.enabled(Rule::BooleanPositionalValueInCall) { + flake8_boolean_trap::rules::boolean_positional_value_in_call(checker, args, func); } if checker.enabled(Rule::Debugger) { flake8_debugger::rules::debugger_call(checker, expr, func); } if checker.enabled(Rule::PandasUseOfInplaceArgument) { - pandas_vet::rules::inplace_argument(checker, expr, func, args, keywords); + pandas_vet::rules::inplace_argument(checker, call); } pandas_vet::rules::call(checker, func); if checker.enabled(Rule::PandasUseOfDotReadTable) { - pandas_vet::rules::use_of_read_table(checker, func, keywords); + pandas_vet::rules::use_of_read_table(checker, call); } if checker.enabled(Rule::PandasUseOfPdMerge) { pandas_vet::rules::use_of_pd_merge(checker, func); } if checker.enabled(Rule::CallDatetimeWithoutTzinfo) { - flake8_datetimez::rules::call_datetime_without_tzinfo( - checker, - func, - args, - keywords, - expr.range(), - ); + flake8_datetimez::rules::call_datetime_without_tzinfo(checker, call); } if checker.enabled(Rule::CallDatetimeToday) { flake8_datetimez::rules::call_datetime_today(checker, func, expr.range()); @@ -707,30 +713,13 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { ); } if checker.enabled(Rule::CallDatetimeNowWithoutTzinfo) { - flake8_datetimez::rules::call_datetime_now_without_tzinfo( - checker, - func, - args, - keywords, - expr.range(), - ); + flake8_datetimez::rules::call_datetime_now_without_tzinfo(checker, call); } if checker.enabled(Rule::CallDatetimeFromtimestamp) { - flake8_datetimez::rules::call_datetime_fromtimestamp( - checker, - func, - args, - keywords, - expr.range(), - ); + flake8_datetimez::rules::call_datetime_fromtimestamp(checker, call); } if checker.enabled(Rule::CallDatetimeStrptimeWithoutZone) { - flake8_datetimez::rules::call_datetime_strptime_without_zone( - checker, - func, - args, - expr.range(), - ); + flake8_datetimez::rules::call_datetime_strptime_without_zone(checker, call); } if checker.enabled(Rule::CallDateToday) { flake8_datetimez::rules::call_date_today(checker, func, expr.range()); @@ -754,18 +743,16 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pylint::rules::bad_str_strip_call(checker, func, args); } if checker.enabled(Rule::InvalidEnvvarDefault) { - pylint::rules::invalid_envvar_default(checker, func, args, keywords); + pylint::rules::invalid_envvar_default(checker, call); } if checker.enabled(Rule::InvalidEnvvarValue) { - pylint::rules::invalid_envvar_value(checker, func, args, keywords); + pylint::rules::invalid_envvar_value(checker, call); } if checker.enabled(Rule::NestedMinMax) { pylint::rules::nested_min_max(checker, expr, func, args, keywords); } if checker.enabled(Rule::PytestPatchWithLambda) { - if let Some(diagnostic) = - flake8_pytest_style::rules::patch_with_lambda(func, args, keywords) - { + if let Some(diagnostic) = flake8_pytest_style::rules::patch_with_lambda(call) { checker.diagnostics.push(diagnostic); } } @@ -776,17 +763,27 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } + if checker.enabled(Rule::PytestUnittestRaisesAssertion) { + if let Some(diagnostic) = + flake8_pytest_style::rules::unittest_raises_assertion(checker, call) + { + checker.diagnostics.push(diagnostic); + } + } if checker.enabled(Rule::SubprocessPopenPreexecFn) { - pylint::rules::subprocess_popen_preexec_fn(checker, func, keywords); + pylint::rules::subprocess_popen_preexec_fn(checker, call); + } + if checker.enabled(Rule::SubprocessRunWithoutCheck) { + pylint::rules::subprocess_run_without_check(checker, call); } if checker.any_enabled(&[ Rule::PytestRaisesWithoutException, Rule::PytestRaisesTooBroad, ]) { - flake8_pytest_style::rules::raises_call(checker, func, args, keywords); + flake8_pytest_style::rules::raises_call(checker, call); } if checker.enabled(Rule::PytestFailWithoutMessage) { - flake8_pytest_style::rules::fail_call(checker, func, args, keywords); + flake8_pytest_style::rules::fail_call(checker, call); } if checker.enabled(Rule::PairwiseOverZipped) { if checker.settings.target_version >= PythonVersion::Py310 { @@ -857,7 +854,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { flake8_use_pathlib::rules::path_constructor_current_directory(checker, expr, func); } if checker.enabled(Rule::OsSepSplit) { - flake8_use_pathlib::rules::os_sep_split(checker, func, args, keywords); + flake8_use_pathlib::rules::os_sep_split(checker, call); } if checker.enabled(Rule::NumpyLegacyRandom) { numpy::rules::legacy_random(checker, func); @@ -872,17 +869,20 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { Rule::LoggingExcInfo, Rule::LoggingRedundantExcInfo, ]) { - flake8_logging_format::rules::logging_call(checker, func, args, keywords); + flake8_logging_format::rules::logging_call(checker, call); } if checker.any_enabled(&[Rule::LoggingTooFewArgs, Rule::LoggingTooManyArgs]) { - pylint::rules::logging_call(checker, func, args, keywords); + pylint::rules::logging_call(checker, call); } if checker.enabled(Rule::DjangoLocalsInRenderFunction) { - flake8_django::rules::locals_in_render_function(checker, func, args, keywords); + flake8_django::rules::locals_in_render_function(checker, call); } - if checker.is_stub && checker.enabled(Rule::UnsupportedMethodCallOnAll) { + if checker.enabled(Rule::UnsupportedMethodCallOnAll) { flake8_pyi::rules::unsupported_method_call_on_all(checker, func); } + if checker.enabled(Rule::QuadraticListSummation) { + ruff::rules::quadratic_list_summation(checker, call); + } } Expr::Dict(ast::ExprDict { keys, @@ -931,7 +931,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pylint::rules::await_outside_async(checker, expr); } } - Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + Expr::FString(ast::ExprFString { values, .. }) => { if checker.enabled(Rule::FStringMissingPlaceholders) { pyflakes::rules::f_string_missing_placeholders(expr, values, checker); } @@ -958,7 +958,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { range: _, }) => { if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = left.as_ref() { @@ -1045,6 +1045,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { checker.locator, ); } + if checker.enabled(Rule::BadStringFormatCharacter) { + pylint::rules::bad_string_format_character::percent(checker, expr); + } if checker.enabled(Rule::BadStringFormatType) { pylint::rules::bad_string_format_type(checker, expr, right); } @@ -1076,7 +1079,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { }) => { // Ex) `str | None` if checker.enabled(Rule::FutureRequiredTypeAnnotation) { - if !checker.is_stub + if !checker.source_type.is_stub() && checker.settings.target_version < PythonVersion::Py310 && !checker.semantic.future_annotations() && checker.semantic.in_annotation() @@ -1088,44 +1091,35 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { ); } } - if checker.is_stub { + + // Avoid duplicate checks if the parent is a union, since these rules already + // traverse nested unions. + if !checker.semantic.in_nested_union() { if checker.enabled(Rule::DuplicateUnionMember) - && checker.semantic.in_type_definition() - // Avoid duplicate checks if the parent is an `|` - && !matches!( - checker.semantic.expr_parent(), - Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..})) - ) + && checker.semantic.in_type_definition() { flake8_pyi::rules::duplicate_union_member(checker, expr); } - if checker.enabled(Rule::UnnecessaryLiteralUnion) - // Avoid duplicate checks if the parent is an `|` - && !matches!( - checker.semantic.expr_parent(), - Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..})) - ) - { + if checker.enabled(Rule::UnnecessaryLiteralUnion) { flake8_pyi::rules::unnecessary_literal_union(checker, expr); } + if checker.enabled(Rule::RedundantLiteralUnion) { + flake8_pyi::rules::redundant_literal_union(checker, expr); + } + if checker.enabled(Rule::UnnecessaryTypeUnion) { + flake8_pyi::rules::unnecessary_type_union(checker, expr); + } } } - Expr::UnaryOp(ast::ExprUnaryOp { - op, - operand, - range: _, - }) => { - let check_not_in = checker.enabled(Rule::NotInTest); - let check_not_is = checker.enabled(Rule::NotIsTest); - if check_not_in || check_not_is { - pycodestyle::rules::not_tests( - checker, - expr, - *op, - operand, - check_not_in, - check_not_is, - ); + Expr::UnaryOp( + unary_op @ ast::ExprUnaryOp { + op, + operand, + range: _, + }, + ) => { + if checker.any_enabled(&[Rule::NotInTest, Rule::NotIsTest]) { + pycodestyle::rules::not_tests(checker, unary_op); } if checker.enabled(Rule::UnaryPrefixIncrementDecrement) { flake8_bugbear::rules::unary_prefix_increment_decrement( @@ -1142,30 +1136,22 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { flake8_simplify::rules::double_negation(checker, expr, *op, operand); } } - Expr::Compare(ast::ExprCompare { - left, - ops, - comparators, - range: _, - }) => { - let check_none_comparisons = checker.enabled(Rule::NoneComparison); - let check_true_false_comparisons = checker.enabled(Rule::TrueFalseComparison); - if check_none_comparisons || check_true_false_comparisons { - pycodestyle::rules::literal_comparisons( - checker, - expr, - left, - ops, - comparators, - check_none_comparisons, - check_true_false_comparisons, - ); + Expr::Compare( + compare @ ast::ExprCompare { + left, + ops, + comparators, + range: _, + }, + ) => { + if checker.any_enabled(&[Rule::NoneComparison, Rule::TrueFalseComparison]) { + pycodestyle::rules::literal_comparisons(checker, compare); } if checker.enabled(Rule::IsLiteral) { pyflakes::rules::invalid_literal_comparison(checker, left, ops, comparators, expr); } if checker.enabled(Rule::TypeComparison) { - pycodestyle::rules::type_comparison(checker, expr, ops, comparators); + pycodestyle::rules::type_comparison(checker, compare); } if checker.any_enabled(&[ Rule::SysVersionCmpStr3, @@ -1196,7 +1182,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pylint::rules::magic_value_comparison(checker, left, comparators); } if checker.enabled(Rule::InDictKeys) { - flake8_simplify::rules::key_in_dict_compare(checker, expr, left, ops, comparators); + flake8_simplify::rules::key_in_dict_compare(checker, compare); } if checker.enabled(Rule::YodaConditions) { flake8_simplify::rules::yoda_conditions(checker, expr, left, ops, comparators); @@ -1216,7 +1202,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { kind: _, range: _, }) => { - if checker.is_stub && checker.enabled(Rule::NumericLiteralTooLong) { + if checker.source_type.is_stub() && checker.enabled(Rule::NumericLiteralTooLong) { flake8_pyi::rules::numeric_literal_too_long(checker, expr); } } @@ -1225,7 +1211,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { kind: _, range: _, }) => { - if checker.is_stub && checker.enabled(Rule::StringOrBytesTooLong) { + if checker.source_type.is_stub() && checker.enabled(Rule::StringOrBytesTooLong) { flake8_pyi::rules::string_or_bytes_too_long(checker, expr); } } @@ -1242,18 +1228,12 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } } if checker.enabled(Rule::HardcodedTempFile) { - if let Some(diagnostic) = flake8_bandit::rules::hardcoded_tmp_directory( - expr, - value, - &checker.settings.flake8_bandit.hardcoded_tmp_directory, - ) { - checker.diagnostics.push(diagnostic); - } + flake8_bandit::rules::hardcoded_tmp_directory(checker, expr, value); } if checker.enabled(Rule::UnicodeKindPrefix) { pyupgrade::rules::unicode_kind_prefix(checker, expr, kind.as_deref()); } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.enabled(Rule::StringOrBytesTooLong) { flake8_pyi::rules::string_or_bytes_too_long(checker, expr); } @@ -1261,7 +1241,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } Expr::Lambda( lambda @ ast::ExprLambda { - args: _, + parameters: _, body: _, range: _, }, diff --git a/crates/ruff/src/checkers/ast/analyze/mod.rs b/crates/ruff/src/checkers/ast/analyze/mod.rs index a8112e5dcf4d3..ed623b1abfdc6 100644 --- a/crates/ruff/src/checkers/ast/analyze/mod.rs +++ b/crates/ruff/src/checkers/ast/analyze/mod.rs @@ -1,5 +1,3 @@ -pub(super) use argument::argument; -pub(super) use arguments::arguments; pub(super) use bindings::bindings; pub(super) use comprehension::comprehension; pub(super) use deferred_for_loops::deferred_for_loops; @@ -8,12 +6,12 @@ pub(super) use definitions::definitions; pub(super) use except_handler::except_handler; pub(super) use expression::expression; pub(super) use module::module; +pub(super) use parameter::parameter; +pub(super) use parameters::parameters; pub(super) use statement::statement; pub(super) use suite::suite; pub(super) use unresolved_references::unresolved_references; -mod argument; -mod arguments; mod bindings; mod comprehension; mod deferred_for_loops; @@ -22,6 +20,8 @@ mod definitions; mod except_handler; mod expression; mod module; +mod parameter; +mod parameters; mod statement; mod suite; mod unresolved_references; diff --git a/crates/ruff/src/checkers/ast/analyze/argument.rs b/crates/ruff/src/checkers/ast/analyze/parameter.rs similarity index 64% rename from crates/ruff/src/checkers/ast/analyze/argument.rs rename to crates/ruff/src/checkers/ast/analyze/parameter.rs index 7b7da0daafa8a..5e6e527c524e1 100644 --- a/crates/ruff/src/checkers/ast/analyze/argument.rs +++ b/crates/ruff/src/checkers/ast/analyze/parameter.rs @@ -1,27 +1,28 @@ -use ruff_python_ast::{Arg, Ranged}; +use ruff_python_ast::{Parameter, Ranged}; use crate::checkers::ast::Checker; use crate::codes::Rule; use crate::rules::{flake8_builtins, pep8_naming, pycodestyle}; -/// Run lint rules over an [`Arg`] syntax node. -pub(crate) fn argument(arg: &Arg, checker: &mut Checker) { +/// Run lint rules over a [`Parameter`] syntax node. +pub(crate) fn parameter(parameter: &Parameter, checker: &mut Checker) { if checker.enabled(Rule::AmbiguousVariableName) { - if let Some(diagnostic) = pycodestyle::rules::ambiguous_variable_name(&arg.arg, arg.range()) + if let Some(diagnostic) = + pycodestyle::rules::ambiguous_variable_name(¶meter.name, parameter.range()) { checker.diagnostics.push(diagnostic); } } if checker.enabled(Rule::InvalidArgumentName) { if let Some(diagnostic) = pep8_naming::rules::invalid_argument_name( - &arg.arg, - arg, + ¶meter.name, + parameter, &checker.settings.pep8_naming.ignore_names, ) { checker.diagnostics.push(diagnostic); } } if checker.enabled(Rule::BuiltinArgumentShadowing) { - flake8_builtins::rules::builtin_argument_shadowing(checker, arg); + flake8_builtins::rules::builtin_argument_shadowing(checker, parameter); } } diff --git a/crates/ruff/src/checkers/ast/analyze/arguments.rs b/crates/ruff/src/checkers/ast/analyze/parameters.rs similarity index 57% rename from crates/ruff/src/checkers/ast/analyze/arguments.rs rename to crates/ruff/src/checkers/ast/analyze/parameters.rs index 36bf02a7b8e01..41d525197bd67 100644 --- a/crates/ruff/src/checkers/ast/analyze/arguments.rs +++ b/crates/ruff/src/checkers/ast/analyze/parameters.rs @@ -1,26 +1,23 @@ -use ruff_python_ast::Arguments; +use ruff_python_ast::Parameters; use crate::checkers::ast::Checker; use crate::codes::Rule; use crate::rules::{flake8_bugbear, flake8_pyi, ruff}; -/// Run lint rules over a [`Arguments`] syntax node. -pub(crate) fn arguments(arguments: &Arguments, checker: &mut Checker) { - if checker.enabled(Rule::MutableArgumentDefault) { - flake8_bugbear::rules::mutable_argument_default(checker, arguments); - } +/// Run lint rules over a [`Parameters`] syntax node. +pub(crate) fn parameters(parameters: &Parameters, checker: &mut Checker) { if checker.enabled(Rule::FunctionCallInDefaultArgument) { - flake8_bugbear::rules::function_call_in_argument_default(checker, arguments); + flake8_bugbear::rules::function_call_in_argument_default(checker, parameters); } if checker.settings.rules.enabled(Rule::ImplicitOptional) { - ruff::rules::implicit_optional(checker, arguments); + ruff::rules::implicit_optional(checker, parameters); } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.enabled(Rule::TypedArgumentDefaultInStub) { - flake8_pyi::rules::typed_argument_simple_defaults(checker, arguments); + flake8_pyi::rules::typed_argument_simple_defaults(checker, parameters); } if checker.enabled(Rule::ArgumentDefaultInStub) { - flake8_pyi::rules::argument_simple_defaults(checker, arguments); + flake8_pyi::rules::argument_simple_defaults(checker, parameters); } } } diff --git a/crates/ruff/src/checkers/ast/analyze/statement.rs b/crates/ruff/src/checkers/ast/analyze/statement.rs index f294ac6c0eecb..892653835c37e 100644 --- a/crates/ruff/src/checkers/ast/analyze/statement.rs +++ b/crates/ruff/src/checkers/ast/analyze/statement.rs @@ -53,7 +53,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::BreakOutsideLoop) { if let Some(diagnostic) = pyflakes::rules::break_outside_loop( stmt, - &mut checker.semantic.parents().skip(1), + &mut checker.semantic.current_statements().skip(1), ) { checker.diagnostics.push(diagnostic); } @@ -63,28 +63,24 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::ContinueOutsideLoop) { if let Some(diagnostic) = pyflakes::rules::continue_outside_loop( stmt, - &mut checker.semantic.parents().skip(1), + &mut checker.semantic.current_statements().skip(1), ) { checker.diagnostics.push(diagnostic); } } } - Stmt::FunctionDef(ast::StmtFunctionDef { - name, - decorator_list, - returns, - args, - body, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - name, - decorator_list, - returns, - args, - body, - .. - }) => { + Stmt::FunctionDef( + function_def @ ast::StmtFunctionDef { + is_async, + name, + decorator_list, + returns, + parameters, + body, + type_params, + range: _, + }, + ) => { if checker.enabled(Rule::DjangoNonLeadingReceiverDecorator) { flake8_django::rules::non_leading_receiver_decorator(checker, decorator_list); } @@ -111,10 +107,10 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if let Some(diagnostic) = pep8_naming::rules::invalid_first_argument_name_for_class_method( checker, - checker.semantic.scope(), + checker.semantic.current_scope(), name, decorator_list, - args, + parameters, ) { checker.diagnostics.push(diagnostic); @@ -123,15 +119,15 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::InvalidFirstArgumentNameForMethod) { if let Some(diagnostic) = pep8_naming::rules::invalid_first_argument_name_for_method( checker, - checker.semantic.scope(), + checker.semantic.current_scope(), name, decorator_list, - args, + parameters, ) { checker.diagnostics.push(diagnostic); } } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.enabled(Rule::PassStatementStubBody) { flake8_pyi::rules::pass_statement_stub_body(checker, body); } @@ -141,41 +137,52 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::StubBodyMultipleStatements) { flake8_pyi::rules::stub_body_multiple_statements(checker, stmt, body); } - if checker.enabled(Rule::AnyEqNeAnnotation) { - flake8_pyi::rules::any_eq_ne_annotation(checker, name, args); - } - if checker.enabled(Rule::NonSelfReturnType) { - flake8_pyi::rules::non_self_return_type( - checker, - stmt, - name, - decorator_list, - returns.as_ref().map(AsRef::as_ref), - args, - stmt.is_async_function_def_stmt(), - ); - } + } + if checker.enabled(Rule::AnyEqNeAnnotation) { + flake8_pyi::rules::any_eq_ne_annotation(checker, name, parameters); + } + if checker.enabled(Rule::NonSelfReturnType) { + flake8_pyi::rules::non_self_return_type( + checker, + stmt, + *is_async, + name, + decorator_list, + returns.as_ref().map(AsRef::as_ref), + parameters, + ); + } + if checker.enabled(Rule::CustomTypeVarReturnType) { + flake8_pyi::rules::custom_type_var_return_type( + checker, + name, + decorator_list, + returns.as_ref().map(AsRef::as_ref), + parameters, + type_params.as_ref(), + ); + } + if checker.source_type.is_stub() { if checker.enabled(Rule::StrOrReprDefinedInStub) { flake8_pyi::rules::str_or_repr_defined_in_stub(checker, stmt); } + } + if checker.source_type.is_stub() + || checker.settings.target_version >= PythonVersion::Py311 + { if checker.enabled(Rule::NoReturnArgumentAnnotationInStub) { - flake8_pyi::rules::no_return_argument_annotation(checker, args); - } - if checker.enabled(Rule::BadExitAnnotation) { - flake8_pyi::rules::bad_exit_annotation( - checker, - stmt.is_async_function_def_stmt(), - name, - args, - ); - } - if checker.enabled(Rule::RedundantNumericUnion) { - flake8_pyi::rules::redundant_numeric_union(checker, args); + flake8_pyi::rules::no_return_argument_annotation(checker, parameters); } } + if checker.enabled(Rule::BadExitAnnotation) { + flake8_pyi::rules::bad_exit_annotation(checker, *is_async, name, parameters); + } + if checker.enabled(Rule::RedundantNumericUnion) { + flake8_pyi::rules::redundant_numeric_union(checker, parameters); + } if checker.enabled(Rule::DunderFunctionName) { if let Some(diagnostic) = pep8_naming::rules::dunder_function_name( - checker.semantic.scope(), + checker.semantic.current_scope(), stmt, name, &checker.settings.pep8_naming.ignore_names, @@ -199,6 +206,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::CachedInstanceMethod) { flake8_bugbear::rules::cached_instance_method(checker, decorator_list); } + if checker.enabled(Rule::MutableArgumentDefault) { + flake8_bugbear::rules::mutable_argument_default(checker, function_def); + } if checker.any_enabled(&[ Rule::UnnecessaryReturnNone, Rule::ImplicitReturnValue, @@ -230,13 +240,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { } } if checker.enabled(Rule::HardcodedPasswordDefault) { - flake8_bandit::rules::hardcoded_password_default(checker, args); + flake8_bandit::rules::hardcoded_password_default(checker, parameters); } if checker.enabled(Rule::PropertyWithParameters) { - pylint::rules::property_with_parameters(checker, stmt, decorator_list, args); + pylint::rules::property_with_parameters(checker, stmt, decorator_list, parameters); } if checker.enabled(Rule::TooManyArguments) { - pylint::rules::too_many_arguments(checker, args, stmt); + pylint::rules::too_many_arguments(checker, parameters, stmt); } if checker.enabled(Rule::TooManyReturnStatements) { if let Some(diagnostic) = pylint::rules::too_many_return_statements( @@ -282,7 +292,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { checker, stmt, name, - args, + parameters, decorator_list, body, ); @@ -290,6 +300,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.any_enabled(&[ Rule::PytestParametrizeNamesWrongType, Rule::PytestParametrizeValuesWrongType, + Rule::PytestDuplicateParametrizeTestCases, ]) { flake8_pytest_style::rules::parametrize(checker, decorator_list); } @@ -299,20 +310,20 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { ]) { flake8_pytest_style::rules::marks(checker, decorator_list); } - if checker.enabled(Rule::BooleanPositionalArgInFunctionDefinition) { - flake8_boolean_trap::rules::check_positional_boolean_in_def( + if checker.enabled(Rule::BooleanTypeHintPositionalArgument) { + flake8_boolean_trap::rules::boolean_type_hint_positional_argument( checker, name, decorator_list, - args, + parameters, ); } - if checker.enabled(Rule::BooleanDefaultValueInFunctionDefinition) { - flake8_boolean_trap::rules::check_boolean_default_value_in_function_definition( + if checker.enabled(Rule::BooleanDefaultValuePositionalArgument) { + flake8_boolean_trap::rules::boolean_default_value_positional_argument( checker, name, decorator_list, - args, + parameters, ); } if checker.enabled(Rule::UnexpectedSpecialMethodSignature) { @@ -321,16 +332,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { stmt, name, decorator_list, - args, + parameters, ); } if checker.enabled(Rule::FStringDocstring) { flake8_bugbear::rules::f_string_docstring(checker, body); } - if checker.enabled(Rule::YieldInForLoop) { - pyupgrade::rules::yield_in_for_loop(checker, stmt); - } - if let ScopeKind::Class(class_def) = checker.semantic.scope().kind { + if let ScopeKind::Class(class_def) = checker.semantic.current_scope().kind { if checker.enabled(Rule::BuiltinAttributeShadowing) { flake8_builtins::rules::builtin_method_shadowing( checker, @@ -363,8 +371,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { Stmt::ClassDef( class_def @ ast::StmtClassDef { name, - bases, - keywords, + arguments, type_params: _, decorator_list, body, @@ -375,23 +382,29 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { flake8_django::rules::nullable_model_string_field(checker, body); } if checker.enabled(Rule::DjangoExcludeWithModelForm) { - if let Some(diagnostic) = - flake8_django::rules::exclude_with_model_form(checker, bases, body) - { + if let Some(diagnostic) = flake8_django::rules::exclude_with_model_form( + checker, + arguments.as_deref(), + body, + ) { checker.diagnostics.push(diagnostic); } } if checker.enabled(Rule::DjangoAllWithModelForm) { if let Some(diagnostic) = - flake8_django::rules::all_with_model_form(checker, bases, body) + flake8_django::rules::all_with_model_form(checker, arguments.as_deref(), body) { checker.diagnostics.push(diagnostic); } } if checker.enabled(Rule::DjangoUnorderedBodyContentInModel) { - flake8_django::rules::unordered_body_content_in_model(checker, bases, body); + flake8_django::rules::unordered_body_content_in_model( + checker, + arguments.as_deref(), + body, + ); } - if !checker.is_stub { + if !checker.source_type.is_stub() { if checker.enabled(Rule::DjangoModelWithoutDunderStr) { flake8_django::rules::model_without_dunder_str(checker, class_def); } @@ -425,39 +438,43 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::ErrorSuffixOnExceptionName) { if let Some(diagnostic) = pep8_naming::rules::error_suffix_on_exception_name( stmt, - bases, + arguments.as_deref(), name, &checker.settings.pep8_naming.ignore_names, ) { checker.diagnostics.push(diagnostic); } } - if !checker.is_stub { + if !checker.source_type.is_stub() { if checker.any_enabled(&[ Rule::AbstractBaseClassWithoutAbstractMethod, Rule::EmptyMethodWithoutAbstractDecorator, ]) { flake8_bugbear::rules::abstract_base_class( - checker, stmt, name, bases, keywords, body, + checker, + stmt, + name, + arguments.as_deref(), + body, ); } } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.enabled(Rule::PassStatementStubBody) { flake8_pyi::rules::pass_statement_stub_body(checker, body); } if checker.enabled(Rule::PassInClassBody) { - flake8_pyi::rules::pass_in_class_body(checker, stmt, body); - } - if checker.enabled(Rule::EllipsisInNonEmptyClassBody) { - flake8_pyi::rules::ellipsis_in_non_empty_class_body(checker, stmt, body); + flake8_pyi::rules::pass_in_class_body(checker, class_def); } } + if checker.enabled(Rule::EllipsisInNonEmptyClassBody) { + flake8_pyi::rules::ellipsis_in_non_empty_class_body(checker, body); + } if checker.enabled(Rule::PytestIncorrectMarkParenthesesStyle) { flake8_pytest_style::rules::marks(checker, decorator_list); } if checker.enabled(Rule::DuplicateClassFieldDefinition) { - flake8_pie::rules::duplicate_class_field_definition(checker, stmt, body); + flake8_pie::rules::duplicate_class_field_definition(checker, body); } if checker.enabled(Rule::NonUniqueEnums) { flake8_pie::rules::non_unique_enums(checker, stmt, body); @@ -478,7 +495,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { flake8_builtins::rules::builtin_variable_shadowing(checker, name, name.range()); } if checker.enabled(Rule::DuplicateBases) { - pylint::rules::duplicate_bases(checker, name, bases); + pylint::rules::duplicate_bases(checker, name, arguments.as_deref()); } if checker.enabled(Rule::NoSlotsInStrSubclass) { flake8_slots::rules::no_slots_in_str_subclass(checker, stmt, class_def); @@ -492,17 +509,16 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::SingleStringSlots) { pylint::rules::single_string_slots(checker, class_def); } + if checker.enabled(Rule::BadDunderMethodName) { + pylint::rules::bad_dunder_method_name(checker, body); + } } Stmt::Import(ast::StmtImport { names, range: _ }) => { if checker.enabled(Rule::MultipleImportsOnOneLine) { pycodestyle::rules::multiple_imports_on_one_line(checker, stmt, names); } if checker.enabled(Rule::ModuleImportNotAtTopOfFile) { - pycodestyle::rules::module_import_not_at_top_of_file( - checker, - stmt, - checker.locator, - ); + pycodestyle::rules::module_import_not_at_top_of_file(checker, stmt); } if checker.enabled(Rule::GlobalStatement) { for name in names { @@ -538,13 +554,30 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { } } if checker.enabled(Rule::BannedApi) { - flake8_tidy_imports::rules::name_or_parent_is_banned( + flake8_tidy_imports::rules::banned_api( checker, - &alias.name, - alias, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchNameOrParent( + flake8_tidy_imports::matchers::MatchNameOrParent { + module: &alias.name, + }, + ), + &alias, ); } - if !checker.is_stub { + + if checker.enabled(Rule::BannedModuleLevelImports) { + flake8_tidy_imports::rules::banned_module_level_imports( + checker, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchNameOrParent( + flake8_tidy_imports::matchers::MatchNameOrParent { + module: &alias.name, + }, + ), + &alias, + ); + } + + if !checker.source_type.is_stub() { if checker.enabled(Rule::UselessImportAlias) { pylint::rules::useless_import_alias(checker, alias); } @@ -658,11 +691,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { let module = module.as_deref(); let level = level.map(|level| level.to_u32()); if checker.enabled(Rule::ModuleImportNotAtTopOfFile) { - pycodestyle::rules::module_import_not_at_top_of_file( - checker, - stmt, - checker.locator, - ); + pycodestyle::rules::module_import_not_at_top_of_file(checker, stmt); } if checker.enabled(Rule::GlobalStatement) { for name in names { @@ -698,16 +727,56 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if let Some(module) = helpers::resolve_imported_module_path(level, module, checker.module_path) { - flake8_tidy_imports::rules::name_or_parent_is_banned(checker, &module, stmt); + flake8_tidy_imports::rules::banned_api( + checker, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchNameOrParent( + flake8_tidy_imports::matchers::MatchNameOrParent { module: &module }, + ), + &stmt, + ); for alias in names { if &alias.name == "*" { continue; } - flake8_tidy_imports::rules::name_is_banned( + flake8_tidy_imports::rules::banned_api( checker, - format!("{module}.{}", alias.name), - alias, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchName( + flake8_tidy_imports::matchers::MatchName { + module: &module, + member: &alias.name, + }, + ), + &alias, + ); + } + } + } + if checker.enabled(Rule::BannedModuleLevelImports) { + if let Some(module) = + helpers::resolve_imported_module_path(level, module, checker.module_path) + { + flake8_tidy_imports::rules::banned_module_level_imports( + checker, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchNameOrParent( + flake8_tidy_imports::matchers::MatchNameOrParent { module: &module }, + ), + &stmt, + ); + + for alias in names { + if &alias.name == "*" { + continue; + } + flake8_tidy_imports::rules::banned_module_level_imports( + checker, + &flake8_tidy_imports::matchers::NameMatchPolicy::MatchName( + flake8_tidy_imports::matchers::MatchName { + module: &module, + member: &alias.name, + }, + ), + &alias, ); } } @@ -719,7 +788,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.enabled(Rule::FutureAnnotationsInStub) { flake8_pyi::rules::from_future_import(checker, import_from); } @@ -739,7 +808,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { } } else if &alias.name == "*" { if checker.enabled(Rule::UndefinedLocalWithNestedImportStarUsage) { - if !matches!(checker.semantic.scope().kind, ScopeKind::Module) { + if !matches!(checker.semantic.current_scope().kind, ScopeKind::Module) { checker.diagnostics.push(Diagnostic::new( pyflakes::rules::UndefinedLocalWithNestedImportStarUsage { name: helpers::format_import_from(level, module), @@ -864,7 +933,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } - if !checker.is_stub { + if !checker.source_type.is_stub() { if checker.enabled(Rule::UselessImportAlias) { pylint::rules::useless_import_alias(checker, alias); } @@ -955,7 +1024,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { flake8_simplify::rules::nested_if_statements( checker, if_, - checker.semantic.stmt_parent(), + checker.semantic.current_statement_parent(), ); } if checker.enabled(Rule::IfWithSameArms) { @@ -977,7 +1046,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { tryceratops::rules::type_check_without_type_error( checker, if_, - checker.semantic.stmt_parent(), + checker.semantic.current_statement_parent(), ); } if checker.enabled(Rule::OutdatedVersionBlock) { @@ -988,7 +1057,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { checker.diagnostics.push(diagnostic); } } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.any_enabled(&[ Rule::UnrecognizedVersionInfoCheck, Rule::PatchVersionComparison, @@ -1070,8 +1139,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { pygrep_hooks::rules::non_existent_mock_method(checker, test); } } - Stmt::With(ast::StmtWith { items, body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::With(with_stmt @ ast::StmtWith { items, body, .. }) => { if checker.enabled(Rule::AssertRaisesException) { flake8_bugbear::rules::assert_raises_exception(checker, items); } @@ -1081,9 +1149,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::MultipleWithStatements) { flake8_simplify::rules::multiple_with_statements( checker, - stmt, - body, - checker.semantic.stmt_parent(), + with_stmt, + checker.semantic.current_statement_parent(), ); } if checker.enabled(Rule::RedefinedLoopName) { @@ -1101,22 +1168,21 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { perflint::rules::try_except_in_loop(checker, body); } } - Stmt::For(ast::StmtFor { - target, - body, - iter, - orelse, - .. - }) - | Stmt::AsyncFor(ast::StmtAsyncFor { - target, - body, - iter, - orelse, - .. - }) => { - if checker.any_enabled(&[Rule::UnusedLoopControlVariable, Rule::IncorrectDictIterator]) - { + Stmt::For( + for_stmt @ ast::StmtFor { + target, + body, + iter, + orelse, + is_async, + .. + }, + ) => { + if checker.any_enabled(&[ + Rule::UnusedLoopControlVariable, + Rule::IncorrectDictIterator, + Rule::YieldInForLoop, + ]) { checker.deferred.for_loops.push(checker.semantic.snapshot()); } if checker.enabled(Rule::LoopVariableOverridesIterator) { @@ -1137,17 +1203,6 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::IterationOverSet) { pylint::rules::iteration_over_set(checker, iter); } - if stmt.is_for_stmt() { - if checker.enabled(Rule::ReimplementedBuiltin) { - flake8_simplify::rules::convert_for_loop_to_any_all(checker, stmt); - } - if checker.enabled(Rule::InDictKeys) { - flake8_simplify::rules::key_in_dict_for(checker, target, iter); - } - if checker.enabled(Rule::TryExceptInLoop) { - perflint::rules::try_except_in_loop(checker, body); - } - } if checker.enabled(Rule::ManualListComprehension) { perflint::rules::manual_list_comprehension(checker, target, body); } @@ -1157,20 +1212,24 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.enabled(Rule::UnnecessaryListCast) { perflint::rules::unnecessary_list_cast(checker, iter); } + if !is_async { + if checker.enabled(Rule::ReimplementedBuiltin) { + flake8_simplify::rules::convert_for_loop_to_any_all(checker, stmt); + } + if checker.enabled(Rule::InDictKeys) { + flake8_simplify::rules::key_in_dict_for(checker, for_stmt); + } + if checker.enabled(Rule::TryExceptInLoop) { + perflint::rules::try_except_in_loop(checker, body); + } + } } Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { if checker.enabled(Rule::JumpStatementInFinally) { flake8_bugbear::rules::jump_statement_in_finally(checker, finalbody); @@ -1300,7 +1359,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.settings.rules.enabled(Rule::TypeBivariance) { pylint::rules::type_bivariance(checker, value); } - if checker.is_stub { + if checker.source_type.is_stub() { if checker.any_enabled(&[ Rule::UnprefixedTypeParam, Rule::AssignmentDefaultInStub, @@ -1311,8 +1370,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { // Ignore assignments in function bodies; those are covered by other rules. if !checker .semantic - .scopes() - .any(|scope| scope.kind.is_any_function()) + .current_scopes() + .any(|scope| scope.kind.is_function()) { if checker.enabled(Rule::UnprefixedTypeParam) { flake8_pyi::rules::prefix_type_params(checker, value, targets); @@ -1337,12 +1396,14 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { } } } - Stmt::AnnAssign(ast::StmtAnnAssign { - target, - value, - annotation, - .. - }) => { + Stmt::AnnAssign( + assign_stmt @ ast::StmtAnnAssign { + target, + value, + annotation, + .. + }, + ) => { if let Some(value) = value { if checker.enabled(Rule::LambdaAssignment) { pycodestyle::rules::lambda_assignment( @@ -1365,14 +1426,17 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { stmt, ); } - if checker.is_stub { + if checker.enabled(Rule::NonPEP695TypeAlias) { + pyupgrade::rules::non_pep695_type_alias(checker, assign_stmt); + } + if checker.source_type.is_stub() { if let Some(value) = value { if checker.enabled(Rule::AssignmentDefaultInStub) { // Ignore assignments in function bodies; those are covered by other rules. if !checker .semantic - .scopes() - .any(|scope| scope.kind.is_any_function()) + .current_scopes() + .any(|scope| scope.kind.is_function()) { flake8_pyi::rules::annotated_assignment_default_in_stub( checker, target, value, annotation, @@ -1386,13 +1450,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { ); } } - if checker.semantic.match_typing_expr(annotation, "TypeAlias") { - if checker.enabled(Rule::SnakeCaseTypeAlias) { - flake8_pyi::rules::snake_case_type_alias(checker, target); - } - if checker.enabled(Rule::TSuffixedTypeAlias) { - flake8_pyi::rules::t_suffixed_type_alias(checker, target); - } + } + if checker.semantic.match_typing_expr(annotation, "TypeAlias") { + if checker.enabled(Rule::SnakeCaseTypeAlias) { + flake8_pyi::rules::snake_case_type_alias(checker, target); + } + if checker.enabled(Rule::TSuffixedTypeAlias) { + flake8_pyi::rules::t_suffixed_type_alias(checker, target); } } } diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 8c4a75db50ff3..d19d212b1979e 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -31,28 +31,31 @@ use std::path::Path; use itertools::Itertools; use log::error; use ruff_python_ast::{ - self as ast, Arg, ArgWithDefault, Arguments, Comprehension, Constant, ElifElseClause, - ExceptHandler, Expr, ExprContext, Keyword, Pattern, Ranged, Stmt, Suite, UnaryOp, + self as ast, Arguments, Comprehension, Constant, ElifElseClause, ExceptHandler, Expr, + ExprContext, Keyword, MatchCase, Parameter, ParameterWithDefault, Parameters, Pattern, Ranged, + Stmt, Suite, UnaryOp, }; use ruff_text_size::{TextRange, TextSize}; use ruff_diagnostics::{Diagnostic, IsolationLevel}; use ruff_python_ast::all::{extract_all_names, DunderAllFlags}; -use ruff_python_ast::helpers::{extract_handled_exceptions, to_module_path}; +use ruff_python_ast::helpers::{ + collect_import_from_member, extract_handled_exceptions, to_module_path, +}; use ruff_python_ast::identifier::Identifier; use ruff_python_ast::str::trailing_quote; use ruff_python_ast::visitor::{walk_except_handler, walk_pattern, Visitor}; -use ruff_python_ast::{helpers, str, visitor}; +use ruff_python_ast::{helpers, str, visitor, PySourceType}; use ruff_python_codegen::{Generator, Quote, Stylist}; use ruff_python_index::Indexer; use ruff_python_parser::typing::{parse_type_annotation, AnnotationKind}; use ruff_python_semantic::analyze::{typing, visibility}; use ruff_python_semantic::{ BindingFlags, BindingId, BindingKind, Exceptions, Export, FromImport, Globals, Import, Module, - ModuleKind, ScopeId, ScopeKind, SemanticModel, SemanticModelFlags, StarImport, SubmoduleImport, + ModuleKind, NodeId, ScopeId, ScopeKind, SemanticModel, SemanticModelFlags, StarImport, + SubmoduleImport, }; use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS}; -use ruff_python_stdlib::path::is_python_stub_file; use ruff_source_file::Locator; use crate::checkers::ast::deferred::Deferred; @@ -74,8 +77,8 @@ pub(crate) struct Checker<'a> { package: Option<&'a Path>, /// The module representation of the current file (e.g., `foo.bar`). module_path: Option<&'a [String]>, - /// Whether the current file is a stub (`.pyi`) file. - is_stub: bool, + /// The [`PySourceType`] of the current file. + pub(crate) source_type: PySourceType, /// The [`flags::Noqa`] for the current analysis (i.e., whether to respect suppression /// comments). noqa: flags::Noqa, @@ -117,6 +120,7 @@ impl<'a> Checker<'a> { stylist: &'a Stylist, indexer: &'a Indexer, importer: Importer<'a>, + source_type: PySourceType, ) -> Checker<'a> { Checker { settings, @@ -125,7 +129,7 @@ impl<'a> Checker<'a> { path, package, module_path: module.path(), - is_stub: is_python_stub_file(path), + source_type, locator, stylist, indexer, @@ -173,13 +177,12 @@ impl<'a> Checker<'a> { /// /// If the current expression in the context is not an f-string, returns ``None``. pub(crate) fn f_string_quote_style(&self) -> Option { - let model = &self.semantic; - if !model.in_f_string() { + if !self.semantic.in_f_string() { return None; } // Find the quote character used to start the containing f-string. - let expr = model.expr()?; + let expr = self.semantic.current_expression()?; let string_range = self.indexer.f_string_range(expr.start())?; let trailing_quote = trailing_quote(self.locator.slice(string_range))?; @@ -191,20 +194,6 @@ impl<'a> Checker<'a> { } } - /// Returns the [`IsolationLevel`] for fixes in the current context. - /// - /// The primary use-case for fix isolation is to ensure that we don't delete all statements - /// in a given indented block, which would cause a syntax error. We therefore need to ensure - /// that we delete at most one statement per indented block per fixer pass. Fix isolation should - /// thus be applied whenever we delete a statement, but can otherwise be omitted. - pub(crate) fn isolation(&self, parent: Option<&Stmt>) -> IsolationLevel { - parent - .and_then(|stmt| self.semantic.stmts.node_id(stmt)) - .map_or(IsolationLevel::default(), |node_id| { - IsolationLevel::Group(node_id.into()) - }) - } - /// The [`Locator`] for the current file, which enables extraction of source code from byte /// offsets. pub(crate) const fn locator(&self) -> &'a Locator<'a> { @@ -253,6 +242,18 @@ impl<'a> Checker<'a> { pub(crate) const fn any_enabled(&self, rules: &[Rule]) -> bool { self.settings.rules.any_enabled(rules) } + + /// Returns the [`IsolationLevel`] to isolate fixes for a given node. + /// + /// The primary use-case for fix isolation is to ensure that we don't delete all statements + /// in a given indented block, which would cause a syntax error. We therefore need to ensure + /// that we delete at most one statement per indented block per fixer pass. Fix isolation should + /// thus be applied whenever we delete a statement, but can otherwise be omitted. + pub(crate) fn isolation(node_id: Option) -> IsolationLevel { + node_id + .map(|node_id| IsolationLevel::Group(node_id.into())) + .unwrap_or_default() + } } impl<'a, 'b> Visitor<'b> for Checker<'a> @@ -261,7 +262,7 @@ where { fn visit_stmt(&mut self, stmt: &'b Stmt) { // Step 0: Pre-processing - self.semantic.push_stmt(stmt); + self.semantic.push_node(stmt); // Track whether we've seen docstrings, non-imports, etc. match stmt { @@ -285,7 +286,7 @@ where self.semantic.flags |= SemanticModelFlags::FUTURES_BOUNDARY; if !self.semantic.seen_import_boundary() && !helpers::is_assignment_to_a_dunder(stmt) - && !helpers::in_nested_block(self.semantic.parents()) + && !helpers::in_nested_block(self.semantic.current_statements()) { self.semantic.flags |= SemanticModelFlags::IMPORT_BOUNDARY; } @@ -319,11 +320,11 @@ where // Given `import foo.bar`, `name` would be "foo", and `qualified_name` would be // "foo.bar". let name = alias.name.split('.').next().unwrap(); - let qualified_name = &alias.name; + let call_path: Box<[&str]> = alias.name.split('.').collect(); self.add_binding( name, alias.identifier(), - BindingKind::SubmoduleImport(SubmoduleImport { qualified_name }), + BindingKind::SubmoduleImport(SubmoduleImport { call_path }), BindingFlags::EXTERNAL, ); } else { @@ -334,17 +335,17 @@ where if alias .asname .as_ref() - .map_or(false, |asname| asname.as_str() == alias.name.as_str()) + .is_some_and(|asname| asname.as_str() == alias.name.as_str()) { flags |= BindingFlags::EXPLICIT_EXPORT; } let name = alias.asname.as_ref().unwrap_or(&alias.name); - let qualified_name = &alias.name; + let call_path: Box<[&str]> = alias.name.split('.').collect(); self.add_binding( name, alias.identifier(), - BindingKind::Import(Import { qualified_name }), + BindingKind::Import(Import { call_path }), flags, ); } @@ -369,7 +370,7 @@ where ); } else if &alias.name == "*" { self.semantic - .scope_mut() + .current_scope_mut() .add_star_import(StarImport { level, module }); } else { let mut flags = BindingFlags::EXTERNAL; @@ -379,7 +380,7 @@ where if alias .asname .as_ref() - .map_or(false, |asname| asname.as_str() == alias.name.as_str()) + .is_some_and(|asname| asname.as_str() == alias.name.as_str()) { flags |= BindingFlags::EXPLICIT_EXPORT; } @@ -388,12 +389,16 @@ where // be "foo.bar". Given `from foo import bar as baz`, `name` would be "baz" // and `qualified_name` would be "foo.bar". let name = alias.asname.as_ref().unwrap_or(&alias.name); - let qualified_name = - helpers::format_import_from_member(level, module, &alias.name); + + // Attempt to resolve any relative imports; but if we don't know the current + // module path, or the relative import extends beyond the package root, + // fallback to a literal representation (e.g., `[".", "foo"]`). + let call_path = collect_import_from_member(level, module, &alias.name) + .into_boxed_slice(); self.add_binding( name, alias.identifier(), - BindingKind::FromImport(FromImport { qualified_name }), + BindingKind::FromImport(FromImport { call_path }), flags, ); } @@ -414,7 +419,7 @@ where BindingKind::Global, BindingFlags::GLOBAL, ); - let scope = self.semantic.scope_mut(); + let scope = self.semantic.current_scope_mut(); scope.add(name, binding_id); } } @@ -437,7 +442,7 @@ where BindingKind::Nonlocal(scope_id), BindingFlags::NONLOCAL, ); - let scope = self.semantic.scope_mut(); + let scope = self.semantic.current_scope_mut(); scope.add(name, binding_id); } } @@ -448,22 +453,16 @@ where // Step 2: Traversal match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { - body, - args, - decorator_list, - returns, - type_params, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - body, - args, - decorator_list, - type_params, - returns, - .. - }) => { + Stmt::FunctionDef( + function_def @ ast::StmtFunctionDef { + body, + parameters, + decorator_list, + returns, + type_params, + .. + }, + ) => { // Visit the decorators and arguments, but avoid the body, which will be // deferred. for decorator in decorator_list { @@ -476,28 +475,28 @@ where self.semantic.push_scope(ScopeKind::Type); - for type_param in type_params { - self.visit_type_param(type_param); + if let Some(type_params) = type_params { + self.visit_type_params(type_params); } - for arg_with_default in args + for parameter_with_default in parameters .posonlyargs .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) { - if let Some(expr) = &arg_with_default.def.annotation { + if let Some(expr) = ¶meter_with_default.parameter.annotation { if runtime_annotation { self.visit_runtime_annotation(expr); } else { self.visit_annotation(expr); }; } - if let Some(expr) = &arg_with_default.default { + if let Some(expr) = ¶meter_with_default.default { self.visit_expr(expr); } } - if let Some(arg) = &args.vararg { + if let Some(arg) = ¶meters.vararg { if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_runtime_annotation(expr); @@ -506,7 +505,7 @@ where }; } } - if let Some(arg) = &args.kwarg { + if let Some(arg) = ¶meters.kwarg { if let Some(expr) = &arg.annotation { if runtime_annotation { self.visit_runtime_annotation(expr); @@ -524,8 +523,7 @@ where } let definition = docstrings::extraction::extract_definition( - ExtractionTarget::Function, - stmt, + ExtractionTarget::Function(function_def), self.semantic.definition_id, &self.semantic.definitions, ); @@ -533,8 +531,7 @@ where self.semantic.push_scope(match &stmt { Stmt::FunctionDef(stmt) => ScopeKind::Function(stmt), - Stmt::AsyncFunctionDef(stmt) => ScopeKind::AsyncFunction(stmt), - _ => unreachable!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef"), + _ => unreachable!("Expected Stmt::FunctionDef"), }); self.deferred.functions.push(self.semantic.snapshot()); @@ -547,8 +544,7 @@ where Stmt::ClassDef( class_def @ ast::StmtClassDef { body, - bases, - keywords, + arguments, decorator_list, type_params, .. @@ -560,19 +556,16 @@ where self.semantic.push_scope(ScopeKind::Type); - for type_param in type_params { - self.visit_type_param(type_param); + if let Some(type_params) = type_params { + self.visit_type_params(type_params); } - for expr in bases { - self.visit_expr(expr); - } - for keyword in keywords { - self.visit_keyword(keyword); + + if let Some(arguments) = arguments { + self.visit_arguments(arguments); } let definition = docstrings::extraction::extract_definition( - ExtractionTarget::Class, - stmt, + ExtractionTarget::Class(class_def), self.semantic.definition_id, &self.semantic.definitions, ); @@ -587,14 +580,14 @@ where self.visit_body(body); } Stmt::TypeAlias(ast::StmtTypeAlias { - range: _range, + range: _, name, type_params, value, }) => { self.semantic.push_scope(ScopeKind::Type); - for type_param in type_params { - self.visit_type_param(type_param); + if let Some(type_params) = type_params { + self.visit_type_params(type_params); } self.visit_expr(value); self.semantic.pop_scope(); @@ -605,14 +598,7 @@ where handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { let mut handled_exceptions = Exceptions::empty(); for type_ in extract_handled_exceptions(handlers) { @@ -632,16 +618,28 @@ where } } + // Iterate over the `body`, then the `handlers`, then the `orelse`, then the + // `finalbody`, but treat the body and the `orelse` as a single branch for + // flow analysis purposes. + let branch = self.semantic.push_branch(); self.semantic.handled_exceptions.push(handled_exceptions); self.visit_body(body); self.semantic.handled_exceptions.pop(); + self.semantic.pop_branch(); for except_handler in handlers { + self.semantic.push_branch(); self.visit_except_handler(except_handler); + self.semantic.pop_branch(); } + self.semantic.set_branch(branch); self.visit_body(orelse); + self.semantic.pop_branch(); + + self.semantic.push_branch(); self.visit_body(finalbody); + self.semantic.pop_branch(); } Stmt::AnnAssign(ast::StmtAnnAssign { target, @@ -653,7 +651,7 @@ where // available at runtime. // See: https://docs.python.org/3/reference/simple_stmts.html#annotated-assignment-statements let runtime_annotation = if self.semantic.future_annotations() { - if self.semantic.scope().kind.is_class() { + if self.semantic.current_scope().kind.is_class() { let baseclasses = &self .settings .flake8_type_checking @@ -672,7 +670,7 @@ where } } else { matches!( - self.semantic.scope().kind, + self.semantic.current_scope().kind, ScopeKind::Class(_) | ScopeKind::Module ) }; @@ -721,6 +719,7 @@ where ) => { self.visit_boolean_test(test); + self.semantic.push_branch(); if typing::is_type_checking_block(stmt_if, &self.semantic) { if self.semantic.at_top_level() { self.importer.visit_type_checking_block(stmt); @@ -729,9 +728,12 @@ where } else { self.visit_body(body); } + self.semantic.pop_branch(); for clause in elif_else_clauses { + self.semantic.push_branch(); self.visit_elif_else_clause(clause); + self.semantic.pop_branch(); } } _ => visitor::walk_stmt(self, stmt), @@ -739,8 +741,7 @@ where // Step 3: Clean-up match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => { + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => { let scope_id = self.semantic.scope_id; self.deferred.scopes.push(scope_id); self.semantic.pop_scope(); // Function scope @@ -773,7 +774,7 @@ where analyze::statement(stmt, self); self.semantic.flags = flags_snapshot; - self.semantic.pop_stmt(); + self.semantic.pop_node(); } fn visit_annotation(&mut self, expr: &'b Expr) { @@ -809,7 +810,7 @@ where return; } - self.semantic.push_expr(expr); + self.semantic.push_node(expr); // Store the flags prior to any further descent, so that we can restore them after visiting // the node. @@ -832,13 +833,12 @@ where match expr { Expr::Call(ast::ExprCall { func, - args: _, - keywords: _, + arguments: _, range: _, }) => { if let Expr::Name(ast::ExprName { id, ctx, range: _ }) = func.as_ref() { if id == "locals" && ctx.is_load() { - let scope = self.semantic.scope_mut(); + let scope = self.semantic.current_scope_mut(); scope.set_uses_locals(); } } @@ -883,24 +883,26 @@ where } Expr::Lambda( lambda @ ast::ExprLambda { - args, + parameters, body: _, range: _, }, ) => { // Visit the default arguments, but avoid the body, which will be deferred. - for ArgWithDefault { - default, - def: _, - range: _, - } in args - .posonlyargs - .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) - { - if let Some(expr) = &default { - self.visit_expr(expr); + if let Some(parameters) = parameters { + for ParameterWithDefault { + default, + parameter: _, + range: _, + } in parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + { + if let Some(expr) = &default { + self.visit_expr(expr); + } } } @@ -919,8 +921,12 @@ where } Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) => { self.visit_expr(func); @@ -1098,7 +1104,7 @@ where arg, range: _, } = keyword; - if arg.as_ref().map_or(false, |arg| arg == "type") { + if arg.as_ref().is_some_and(|arg| arg == "type") { self.visit_type_definition(value); } else { self.visit_non_type_definition(value); @@ -1200,7 +1206,7 @@ where )); } } - Expr::JoinedStr(_) => { + Expr::FString(_) => { self.semantic.flags |= SemanticModelFlags::F_STRING; visitor::walk_expr(self, expr); } @@ -1224,7 +1230,7 @@ where analyze::expression(expr, self); self.semantic.flags = flags_snapshot; - self.semantic.pop_expr(); + self.semantic.pop_node(); } fn visit_except_handler(&mut self, except_handler: &'b ExceptHandler) { @@ -1279,7 +1285,7 @@ where fn visit_format_spec(&mut self, format_spec: &'b Expr) { match format_spec { - Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + Expr::FString(ast::ExprFString { values, .. }) => { for value in values { self.visit_expr(value); } @@ -1288,43 +1294,43 @@ where } } - fn visit_arguments(&mut self, arguments: &'b Arguments) { + fn visit_parameters(&mut self, parameters: &'b Parameters) { // Step 1: Binding. // Bind, but intentionally avoid walking default expressions, as we handle them // upstream. - for arg_with_default in &arguments.posonlyargs { - self.visit_arg(&arg_with_default.def); + for parameter_with_default in ¶meters.posonlyargs { + self.visit_parameter(¶meter_with_default.parameter); } - for arg_with_default in &arguments.args { - self.visit_arg(&arg_with_default.def); + for parameter_with_default in ¶meters.args { + self.visit_parameter(¶meter_with_default.parameter); } - if let Some(arg) = &arguments.vararg { - self.visit_arg(arg); + if let Some(arg) = ¶meters.vararg { + self.visit_parameter(arg); } - for arg_with_default in &arguments.kwonlyargs { - self.visit_arg(&arg_with_default.def); + for parameter_with_default in ¶meters.kwonlyargs { + self.visit_parameter(¶meter_with_default.parameter); } - if let Some(arg) = &arguments.kwarg { - self.visit_arg(arg); + if let Some(arg) = ¶meters.kwarg { + self.visit_parameter(arg); } // Step 4: Analysis - analyze::arguments(arguments, self); + analyze::parameters(parameters, self); } - fn visit_arg(&mut self, arg: &'b Arg) { + fn visit_parameter(&mut self, parameter: &'b Parameter) { // Step 1: Binding. // Bind, but intentionally avoid walking the annotation, as we handle it // upstream. self.add_binding( - &arg.arg, - arg.identifier(), + ¶meter.name, + parameter.identifier(), BindingKind::Argument, BindingFlags::empty(), ); // Step 4: Analysis - analyze::argument(arg, self); + analyze::parameter(parameter, self); } fn visit_pattern(&mut self, pattern: &'b Pattern) { @@ -1362,6 +1368,17 @@ where } } + fn visit_match_case(&mut self, match_case: &'b MatchCase) { + self.visit_pattern(&match_case.pattern); + if let Some(expr) = &match_case.guard { + self.visit_expr(expr); + } + + self.semantic.push_branch(); + self.visit_body(&match_case.body); + self.semantic.pop_branch(); + } + fn visit_type_param(&mut self, type_param: &'b ast::TypeParam) { // Step 1: Binding match type_param { @@ -1604,7 +1621,7 @@ impl<'a> Checker<'a> { } fn handle_node_store(&mut self, id: &'a str, expr: &Expr) { - let parent = self.semantic.stmt(); + let parent = self.semantic.current_statement(); if matches!( parent, @@ -1619,7 +1636,7 @@ impl<'a> Checker<'a> { return; } - if matches!(parent, Stmt::For(_) | Stmt::AsyncFor(_)) { + if parent.is_for_stmt() { self.add_binding( id, expr.range(), @@ -1639,7 +1656,7 @@ impl<'a> Checker<'a> { return; } - let scope = self.semantic.scope(); + let scope = self.semantic.current_scope(); if scope.kind.is_module() && match parent { @@ -1691,8 +1708,8 @@ impl<'a> Checker<'a> { if self .semantic - .expr_ancestors() - .any(|expr| expr.is_named_expr_expr()) + .current_expressions() + .any(Expr::is_named_expr_expr) { self.add_binding( id, @@ -1718,7 +1735,7 @@ impl<'a> Checker<'a> { self.semantic.resolve_del(id, expr.range()); - if helpers::on_conditional_branch(&mut self.semantic.parents()) { + if helpers::on_conditional_branch(&mut self.semantic.current_statements()) { return; } @@ -1726,7 +1743,7 @@ impl<'a> Checker<'a> { let binding_id = self.semantic .push_binding(expr.range(), BindingKind::Deletion, BindingFlags::empty()); - let scope = self.semantic.scope_mut(); + let scope = self.semantic.current_scope_mut(); scope.add(id, binding_id); } @@ -1780,7 +1797,7 @@ impl<'a> Checker<'a> { pyupgrade::rules::quoted_annotation(self, value, range); } } - if self.is_stub { + if self.source_type.is_stub() { if self.enabled(Rule::QuotedAnnotationInStub) { flake8_pyi::rules::quoted_annotation_in_stub(self, value, range); } @@ -1818,15 +1835,14 @@ impl<'a> Checker<'a> { for snapshot in deferred_functions { self.semantic.restore(snapshot); - match &self.semantic.stmt() { - Stmt::FunctionDef(ast::StmtFunctionDef { body, args, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, args, .. }) => { - self.visit_arguments(args); - self.visit_body(body); - } - _ => { - unreachable!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef") - } + if let Stmt::FunctionDef(ast::StmtFunctionDef { + body, parameters, .. + }) = self.semantic.current_statement() + { + self.visit_parameters(parameters); + self.visit_body(body); + } else { + unreachable!("Expected Stmt::FunctionDef") } } } @@ -1841,12 +1857,14 @@ impl<'a> Checker<'a> { self.semantic.restore(snapshot); if let Expr::Lambda(ast::ExprLambda { - args, + parameters, body, range: _, }) = expr { - self.visit_arguments(args); + if let Some(parameters) = parameters { + self.visit_parameters(parameters); + } self.visit_expr(body); } else { unreachable!("Expected Expr::Lambda"); @@ -1867,7 +1885,7 @@ impl<'a> Checker<'a> { .map(|binding_id| &self.semantic.bindings[binding_id]) .filter_map(|binding| match &binding.kind { BindingKind::Export(Export { names }) => { - Some(names.iter().map(|name| (*name, binding.range))) + Some(names.iter().map(|name| (*name, binding.range()))) } _ => None, }) @@ -1918,6 +1936,7 @@ pub(crate) fn check_ast( noqa: flags::Noqa, path: &Path, package: Option<&Path>, + source_type: PySourceType, ) -> Vec { let module_path = package.and_then(|package| to_module_path(package, path)); let module = Module { @@ -1945,6 +1964,7 @@ pub(crate) fn check_ast( stylist, indexer, Importer::new(python_ast, locator, stylist), + source_type, ); checker.bind_builtins(); diff --git a/crates/ruff/src/checkers/imports.rs b/crates/ruff/src/checkers/imports.rs index 7eb17a2eca30d..d0ee5096577f9 100644 --- a/crates/ruff/src/checkers/imports.rs +++ b/crates/ruff/src/checkers/imports.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::path::Path; -use ruff_python_ast::{self as ast, Ranged, Stmt, Suite}; +use ruff_python_ast::{self as ast, PySourceType, Ranged, Stmt, Suite}; use ruff_diagnostics::Diagnostic; use ruff_python_ast::helpers::to_module_path; @@ -10,7 +10,7 @@ use ruff_python_ast::imports::{ImportMap, ModuleImport}; use ruff_python_ast::statement_visitor::StatementVisitor; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; -use ruff_python_stdlib::path::is_python_stub_file; + use ruff_source_file::Locator; use crate::directives::IsortDirectives; @@ -87,12 +87,12 @@ pub(crate) fn check_imports( path: &Path, package: Option<&Path>, source_kind: Option<&SourceKind>, + source_type: PySourceType, ) -> (Vec, Option) { - let is_stub = is_python_stub_file(path); - // Extract all import blocks from the AST. let tracker = { - let mut tracker = BlockBuilder::new(locator, directives, is_stub, source_kind); + let mut tracker = + BlockBuilder::new(locator, directives, source_type.is_stub(), source_kind); tracker.visit_body(python_ast); tracker }; @@ -104,7 +104,13 @@ pub(crate) fn check_imports( for block in &blocks { if !block.imports.is_empty() { if let Some(diagnostic) = isort::rules::organize_imports( - block, locator, stylist, indexer, settings, package, + block, + locator, + stylist, + indexer, + settings, + package, + source_type, ) { diagnostics.push(diagnostic); } @@ -113,7 +119,11 @@ pub(crate) fn check_imports( } if settings.rules.enabled(Rule::MissingRequiredImport) { diagnostics.extend(isort::rules::add_required_imports( - python_ast, locator, stylist, settings, is_stub, + python_ast, + locator, + stylist, + settings, + source_type, )); } diff --git a/crates/ruff/src/checkers/logical_lines.rs b/crates/ruff/src/checkers/logical_lines.rs index 95cad2f647015..b02514ab65364 100644 --- a/crates/ruff/src/checkers/logical_lines.rs +++ b/crates/ruff/src/checkers/logical_lines.rs @@ -1,10 +1,10 @@ -use ruff_python_parser::lexer::LexResult; -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, DiagnosticKind}; +use ruff_python_ast::Ranged; use ruff_python_codegen::Stylist; +use ruff_python_parser::lexer::LexResult; use ruff_python_parser::TokenKind; use ruff_source_file::Locator; +use ruff_text_size::TextRange; use crate::registry::{AsRule, Rule}; use crate::rules::pycodestyle::rules::logical_lines::{ diff --git a/crates/ruff/src/checkers/noqa.rs b/crates/ruff/src/checkers/noqa.rs index 2916ad7339d62..e234fc80393ba 100644 --- a/crates/ruff/src/checkers/noqa.rs +++ b/crates/ruff/src/checkers/noqa.rs @@ -94,8 +94,15 @@ pub(crate) fn check_noqa( } } - // Enforce that the noqa directive was actually used (RUF100). - if analyze_directives && settings.rules.enabled(Rule::UnusedNOQA) { + // Enforce that the noqa directive was actually used (RUF100), unless RUF100 was itself + // suppressed. + if settings.rules.enabled(Rule::UnusedNOQA) + && analyze_directives + && !exemption.is_some_and(|exemption| match exemption { + FileExemption::All => true, + FileExemption::Codes(codes) => codes.contains(&Rule::UnusedNOQA.noqa_code()), + }) + { for line in noqa_directives.lines() { match &line.directive { Directive::All(directive) => { @@ -103,8 +110,8 @@ pub(crate) fn check_noqa( let mut diagnostic = Diagnostic::new(UnusedNOQA { codes: None }, directive.range()); if settings.rules.should_fix(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.set_fix_from_edit(delete_noqa(directive.range(), locator)); + diagnostic + .set_fix(Fix::automatic(delete_noqa(directive.range(), locator))); } diagnostics.push(diagnostic); } @@ -168,12 +175,12 @@ pub(crate) fn check_noqa( ); if settings.rules.should_fix(diagnostic.kind.rule()) { if valid_codes.is_empty() { - #[allow(deprecated)] - diagnostic - .set_fix_from_edit(delete_noqa(directive.range(), locator)); + diagnostic.set_fix(Fix::automatic(delete_noqa( + directive.range(), + locator, + ))); } else { - #[allow(deprecated)] - diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( + diagnostic.set_fix(Fix::automatic(Edit::range_replacement( format!("# noqa: {}", valid_codes.join(", ")), directive.range(), ))); diff --git a/crates/ruff/src/codes.rs b/crates/ruff/src/codes.rs index 9018dcc946980..db1ab2831c04b 100644 --- a/crates/ruff/src/codes.rs +++ b/crates/ruff/src/codes.rs @@ -191,6 +191,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pylint, "E1142") => (RuleGroup::Unspecified, rules::pylint::rules::AwaitOutsideAsync), (Pylint, "E1205") => (RuleGroup::Unspecified, rules::pylint::rules::LoggingTooManyArgs), (Pylint, "E1206") => (RuleGroup::Unspecified, rules::pylint::rules::LoggingTooFewArgs), + (Pylint, "E1300") => (RuleGroup::Unspecified, rules::pylint::rules::BadStringFormatCharacter), (Pylint, "E1307") => (RuleGroup::Unspecified, rules::pylint::rules::BadStringFormatType), (Pylint, "E1310") => (RuleGroup::Unspecified, rules::pylint::rules::BadStrStripCall), (Pylint, "E1507") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidEnvvarValue), @@ -215,6 +216,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pylint, "R1722") => (RuleGroup::Unspecified, rules::pylint::rules::SysExitAlias), (Pylint, "R2004") => (RuleGroup::Unspecified, rules::pylint::rules::MagicValueComparison), (Pylint, "R5501") => (RuleGroup::Unspecified, rules::pylint::rules::CollapsibleElseIf), + (Pylint, "R6301") => (RuleGroup::Nursery, rules::pylint::rules::NoSelfUse), (Pylint, "W0120") => (RuleGroup::Unspecified, rules::pylint::rules::UselessElseOnLoop), (Pylint, "W0127") => (RuleGroup::Unspecified, rules::pylint::rules::SelfAssigningVariable), (Pylint, "W0129") => (RuleGroup::Unspecified, rules::pylint::rules::AssertOnStringLiteral), @@ -225,8 +227,10 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pylint, "W0711") => (RuleGroup::Unspecified, rules::pylint::rules::BinaryOpException), (Pylint, "W1508") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidEnvvarDefault), (Pylint, "W1509") => (RuleGroup::Unspecified, rules::pylint::rules::SubprocessPopenPreexecFn), + (Pylint, "W1510") => (RuleGroup::Unspecified, rules::pylint::rules::SubprocessRunWithoutCheck), (Pylint, "W1641") => (RuleGroup::Nursery, rules::pylint::rules::EqWithoutHash), (Pylint, "W2901") => (RuleGroup::Unspecified, rules::pylint::rules::RedefinedLoopName), + (Pylint, "W3201") => (RuleGroup::Nursery, rules::pylint::rules::BadDunderMethodName), (Pylint, "W3301") => (RuleGroup::Unspecified, rules::pylint::rules::NestedMinMax), // flake8-async @@ -308,6 +312,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { // flake8-tidy-imports (Flake8TidyImports, "251") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::BannedApi), (Flake8TidyImports, "252") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::RelativeImports), + (Flake8TidyImports, "253") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::BannedModuleLevelImports), // flake8-return (Flake8Return, "501") => (RuleGroup::Unspecified, rules::flake8_return::rules::UnnecessaryReturnNone), @@ -438,6 +443,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pyupgrade, "037") => (RuleGroup::Unspecified, rules::pyupgrade::rules::QuotedAnnotation), (Pyupgrade, "038") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP604Isinstance), (Pyupgrade, "039") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryClassParentheses), + (Pyupgrade, "040") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP695TypeAlias), // pydocstyle (Pydocstyle, "100") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicModule), @@ -563,9 +569,9 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Bandit, "701") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::Jinja2AutoescapeFalse), // flake8-boolean-trap - (Flake8BooleanTrap, "001") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalArgInFunctionDefinition), - (Flake8BooleanTrap, "002") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanDefaultValueInFunctionDefinition), - (Flake8BooleanTrap, "003") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalValueInFunctionCall), + (Flake8BooleanTrap, "001") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanTypeHintPositionalArgument), + (Flake8BooleanTrap, "002") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanDefaultValuePositionalArgument), + (Flake8BooleanTrap, "003") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalValueInCall), // flake8-unused-arguments (Flake8UnusedArguments, "001") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedFunctionArgument), @@ -636,6 +642,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Pyi, "016") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::DuplicateUnionMember), (Flake8Pyi, "017") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::ComplexAssignmentInStub), (Flake8Pyi, "018") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateTypeVar), + (Flake8Pyi, "019") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::CustomTypeVarReturnType), (Flake8Pyi, "020") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::QuotedAnnotationInStub), (Flake8Pyi, "021") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::DocstringInStub), (Flake8Pyi, "024") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::CollectionsNamedTuple), @@ -658,9 +665,11 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Pyi, "048") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::StubBodyMultipleStatements), (Flake8Pyi, "049") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateTypedDict), (Flake8Pyi, "050") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NoReturnArgumentAnnotationInStub), + (Flake8Pyi, "051") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::RedundantLiteralUnion), (Flake8Pyi, "052") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnannotatedAssignmentInStub), (Flake8Pyi, "054") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NumericLiteralTooLong), (Flake8Pyi, "053") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::StringOrBytesTooLong), + (Flake8Pyi, "055") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnnecessaryTypeUnion), (Flake8Pyi, "056") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnsupportedMethodCallOnAll), // flake8-pytest-style @@ -677,6 +686,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8PytestStyle, "011") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestRaisesTooBroad), (Flake8PytestStyle, "012") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestRaisesWithMultipleStatements), (Flake8PytestStyle, "013") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestIncorrectPytestImport), + (Flake8PytestStyle, "014") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestDuplicateParametrizeTestCases), (Flake8PytestStyle, "015") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestAssertAlwaysFalse), (Flake8PytestStyle, "016") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFailWithoutMessage), (Flake8PytestStyle, "017") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestAssertInExcept), @@ -689,6 +699,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8PytestStyle, "024") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUnnecessaryAsyncioMarkOnFixture), (Flake8PytestStyle, "025") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestErroneousUseFixturesOnFixture), (Flake8PytestStyle, "026") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUseFixturesWithoutParameters), + (Flake8PytestStyle, "027") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUnittestRaisesAssertion), // flake8-pie (Flake8Pie, "790") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryPass), @@ -697,6 +708,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Pie, "800") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessarySpread), (Flake8Pie, "804") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryDictKwargs), (Flake8Pie, "807") => (RuleGroup::Unspecified, rules::flake8_pie::rules::ReimplementedListBuiltin), + (Flake8Pie, "808") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryRangeStart), (Flake8Pie, "810") => (RuleGroup::Unspecified, rules::flake8_pie::rules::MultipleStartsEndsWith), // flake8-commas @@ -806,6 +818,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Ruff, "014") => (RuleGroup::Nursery, rules::ruff::rules::UnreachableCode), (Ruff, "015") => (RuleGroup::Unspecified, rules::ruff::rules::UnnecessaryIterableAllocationForFirstElement), (Ruff, "016") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidIndexType), + (Ruff, "017") => (RuleGroup::Nursery, rules::ruff::rules::QuadraticListSummation), (Ruff, "100") => (RuleGroup::Unspecified, rules::ruff::rules::UnusedNOQA), (Ruff, "200") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidPyprojectToml), diff --git a/crates/ruff/src/cst/matchers.rs b/crates/ruff/src/cst/matchers.rs index dad1e689eb142..70cc4b3aa351d 100644 --- a/crates/ruff/src/cst/matchers.rs +++ b/crates/ruff/src/cst/matchers.rs @@ -1,9 +1,11 @@ +use crate::autofix::codemods::CodegenStylist; use anyhow::{bail, Result}; use libcst_native::{ Arg, Attribute, Call, Comparison, CompoundStatement, Dict, Expression, FunctionDef, GeneratorExp, If, Import, ImportAlias, ImportFrom, ImportNames, IndentedBlock, Lambda, ListComp, Module, Name, SmallStatement, Statement, Suite, Tuple, With, }; +use ruff_python_codegen::Stylist; pub(crate) fn match_module(module_text: &str) -> Result { match libcst_native::parse_module(module_text, None) { @@ -12,13 +14,6 @@ pub(crate) fn match_module(module_text: &str) -> Result { } } -pub(crate) fn match_expression(expression_text: &str) -> Result { - match libcst_native::parse_expression(expression_text) { - Ok(expression) => Ok(expression), - Err(_) => bail!("Failed to extract expression from source"), - } -} - pub(crate) fn match_statement(statement_text: &str) -> Result { match libcst_native::parse_statement(statement_text) { Ok(statement) => Ok(statement), @@ -205,3 +200,59 @@ pub(crate) fn match_if<'a, 'b>(statement: &'a mut Statement<'b>) -> Result<&'a m bail!("Expected Statement::Compound") } } + +/// Given the source code for an expression, return the parsed [`Expression`]. +/// +/// If the expression is not guaranteed to be valid as a standalone expression (e.g., if it may +/// span multiple lines and/or require parentheses), use [`transform_expression`] instead. +pub(crate) fn match_expression(expression_text: &str) -> Result { + match libcst_native::parse_expression(expression_text) { + Ok(expression) => Ok(expression), + Err(_) => bail!("Failed to extract expression from source"), + } +} + +/// Run a transformation function over an expression. +/// +/// Passing an expression to [`match_expression`] directly can lead to parse errors if the +/// expression is not a valid standalone expression (e.g., it was parenthesized in the original +/// source). This method instead wraps the expression in "fake" parentheses, runs the +/// transformation, then removes the "fake" parentheses. +pub(crate) fn transform_expression( + source_code: &str, + stylist: &Stylist, + func: impl FnOnce(Expression) -> Result, +) -> Result { + // Wrap the expression in parentheses. + let source_code = format!("({source_code})"); + let expression = match_expression(&source_code)?; + + // Run the function on the expression. + let expression = func(expression)?; + + // Codegen the expression. + let mut source_code = expression.codegen_stylist(stylist); + + // Drop the outer parentheses. + source_code.drain(0..1); + source_code.drain(source_code.len() - 1..source_code.len()); + Ok(source_code) +} + +/// Like [`transform_expression`], but operates on the source code of the expression, rather than +/// the parsed [`Expression`]. This _shouldn't_ exist, but does to accommodate lifetime issues. +pub(crate) fn transform_expression_text( + source_code: &str, + func: impl FnOnce(String) -> Result, +) -> Result { + // Wrap the expression in parentheses. + let source_code = format!("({source_code})"); + + // Run the function on the expression. + let mut transformed = func(source_code)?; + + // Drop the outer parentheses. + transformed.drain(0..1); + transformed.drain(transformed.len() - 1..transformed.len()); + Ok(transformed) +} diff --git a/crates/ruff/src/directives.rs b/crates/ruff/src/directives.rs index 1ed7d20c3d8b5..59b2a4c572cd1 100644 --- a/crates/ruff/src/directives.rs +++ b/crates/ruff/src/directives.rs @@ -405,7 +405,7 @@ y = 2 z = x + 1"; assert_eq!( noqa_mappings(contents), - NoqaMapping::from_iter([TextRange::new(TextSize::from(0), TextSize::from(22)),]) + NoqaMapping::from_iter([TextRange::new(TextSize::from(0), TextSize::from(22))]) ); let contents = "x = 1 diff --git a/crates/ruff/src/docstrings/extraction.rs b/crates/ruff/src/docstrings/extraction.rs index 3a2fdb766048b..c642b7527176e 100644 --- a/crates/ruff/src/docstrings/extraction.rs +++ b/crates/ruff/src/docstrings/extraction.rs @@ -1,7 +1,6 @@ //! Extract docstrings from an AST. use ruff_python_ast::{self as ast, Constant, Expr, Stmt}; - use ruff_python_semantic::{Definition, DefinitionId, Definitions, Member, MemberKind}; /// Extract a docstring from a function or class body. @@ -28,63 +27,48 @@ pub(crate) fn docstring_from(suite: &[Stmt]) -> Option<&Expr> { pub(crate) fn extract_docstring<'a>(definition: &'a Definition<'a>) -> Option<&'a Expr> { match definition { Definition::Module(module) => docstring_from(module.python_ast), - Definition::Member(member) => { - if let Stmt::ClassDef(ast::StmtClassDef { body, .. }) - | Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) = &member.stmt - { - docstring_from(body) - } else { - None - } - } + Definition::Member(member) => docstring_from(member.body()), } } #[derive(Copy, Clone)] -pub(crate) enum ExtractionTarget { - Class, - Function, +pub(crate) enum ExtractionTarget<'a> { + Class(&'a ast::StmtClassDef), + Function(&'a ast::StmtFunctionDef), } /// Extract a `Definition` from the AST node defined by a `Stmt`. pub(crate) fn extract_definition<'a>( - target: ExtractionTarget, - stmt: &'a Stmt, + target: ExtractionTarget<'a>, parent: DefinitionId, definitions: &Definitions<'a>, ) -> Member<'a> { match target { - ExtractionTarget::Function => match &definitions[parent] { + ExtractionTarget::Function(function) => match &definitions[parent] { Definition::Module(..) => Member { parent, - kind: MemberKind::Function, - stmt, + kind: MemberKind::Function(function), }, Definition::Member(Member { - kind: MemberKind::Class | MemberKind::NestedClass, + kind: MemberKind::Class(_) | MemberKind::NestedClass(_), .. }) => Member { parent, - kind: MemberKind::Method, - stmt, + kind: MemberKind::Method(function), }, - Definition::Member(..) => Member { + Definition::Member(_) => Member { parent, - kind: MemberKind::NestedFunction, - stmt, + kind: MemberKind::NestedFunction(function), }, }, - ExtractionTarget::Class => match &definitions[parent] { - Definition::Module(..) => Member { + ExtractionTarget::Class(class) => match &definitions[parent] { + Definition::Module(_) => Member { parent, - kind: MemberKind::Class, - stmt, + kind: MemberKind::Class(class), }, - Definition::Member(..) => Member { + Definition::Member(_) => Member { parent, - kind: MemberKind::NestedClass, - stmt, + kind: MemberKind::NestedClass(class), }, }, } diff --git a/crates/ruff/src/docstrings/mod.rs b/crates/ruff/src/docstrings/mod.rs index 46db0dcf35b41..92726c8d97aa0 100644 --- a/crates/ruff/src/docstrings/mod.rs +++ b/crates/ruff/src/docstrings/mod.rs @@ -2,9 +2,8 @@ use std::fmt::{Debug, Formatter}; use std::ops::Deref; use ruff_python_ast::{Expr, Ranged}; -use ruff_text_size::{TextRange, TextSize}; - use ruff_python_semantic::Definition; +use ruff_text_size::TextRange; pub(crate) mod extraction; pub(crate) mod google; @@ -28,21 +27,15 @@ impl<'a> Docstring<'a> { DocstringBody { docstring: self } } - pub(crate) fn start(&self) -> TextSize { - self.expr.start() - } - - pub(crate) fn end(&self) -> TextSize { - self.expr.end() + pub(crate) fn leading_quote(&self) -> &'a str { + &self.contents[TextRange::up_to(self.body_range.start())] } +} - pub(crate) fn range(&self) -> TextRange { +impl Ranged for Docstring<'_> { + fn range(&self) -> TextRange { self.expr.range() } - - pub(crate) fn leading_quote(&self) -> &'a str { - &self.contents[TextRange::up_to(self.body_range.start())] - } } #[derive(Copy, Clone)] @@ -51,18 +44,15 @@ pub(crate) struct DocstringBody<'a> { } impl<'a> DocstringBody<'a> { - #[inline] - pub(crate) fn start(self) -> TextSize { - self.range().start() + pub(crate) fn as_str(self) -> &'a str { + &self.docstring.contents[self.docstring.body_range] } +} - pub(crate) fn range(self) -> TextRange { +impl Ranged for DocstringBody<'_> { + fn range(&self) -> TextRange { self.docstring.body_range + self.docstring.start() } - - pub(crate) fn as_str(self) -> &'a str { - &self.docstring.contents[self.docstring.body_range] - } } impl Deref for DocstringBody<'_> { diff --git a/crates/ruff/src/docstrings/sections.rs b/crates/ruff/src/docstrings/sections.rs index d8f6aa2a55d2b..58d8339e101c1 100644 --- a/crates/ruff/src/docstrings/sections.rs +++ b/crates/ruff/src/docstrings/sections.rs @@ -2,6 +2,7 @@ use std::fmt::{Debug, Formatter}; use std::iter::FusedIterator; use ruff_python_ast::docstrings::{leading_space, leading_words}; +use ruff_python_ast::Ranged; use ruff_text_size::{TextLen, TextRange, TextSize}; use strum_macros::EnumIter; @@ -366,6 +367,12 @@ impl<'a> SectionContext<'a> { } } +impl Ranged for SectionContext<'_> { + fn range(&self) -> TextRange { + self.range() + } +} + impl Debug for SectionContext<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("SectionContext") @@ -402,7 +409,7 @@ fn is_docstring_section( } // Determine whether the next line is an underline, e.g., "-----". - let next_line_is_underline = next_line.map_or(false, |next_line| { + let next_line_is_underline = next_line.is_some_and(|next_line| { let next_line = next_line.trim(); if next_line.is_empty() { false diff --git a/crates/ruff/src/fs.rs b/crates/ruff/src/fs.rs index c8ff19546821d..2a617113fe2ee 100644 --- a/crates/ruff/src/fs.rs +++ b/crates/ruff/src/fs.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use globset::GlobMatcher; use log::debug; -use path_absolutize::{path_dedot, Absolutize}; +use path_absolutize::Absolutize; use crate::registry::RuleSet; @@ -61,7 +61,13 @@ pub fn normalize_path_to, R: AsRef>(path: P, project_root: /// Convert an absolute path to be relative to the current working directory. pub fn relativize_path>(path: P) -> String { let path = path.as_ref(); - if let Ok(path) = path.strip_prefix(&*path_dedot::CWD) { + + #[cfg(target_arch = "wasm32")] + let cwd = Path::new("."); + #[cfg(not(target_arch = "wasm32"))] + let cwd = path_absolutize::path_dedot::CWD.as_path(); + + if let Ok(path) = path.strip_prefix(cwd) { return format!("{}", path.display()); } format!("{}", path.display()) diff --git a/crates/ruff/src/importer/insertion.rs b/crates/ruff/src/importer/insertion.rs index 7d5e2aaf94c33..92c335a2df582 100644 --- a/crates/ruff/src/importer/insertion.rs +++ b/crates/ruff/src/importer/insertion.rs @@ -1,8 +1,8 @@ //! Insert statements into Python code. use std::ops::Add; -use ruff_python_ast::{Ranged, Stmt}; -use ruff_python_parser::{lexer, Mode, Tok}; +use ruff_python_ast::{PySourceType, Ranged, Stmt}; +use ruff_python_parser::{lexer, AsMode, Tok}; use ruff_text_size::TextSize; use ruff_diagnostics::Edit; @@ -67,9 +67,13 @@ impl<'a> Insertion<'a> { TextSize::default() }; - // Skip over commented lines. + // Skip over commented lines, with whitespace separation. for line in UniversalNewlineIterator::with_offset(locator.after(location), location) { - if line.trim_whitespace_start().starts_with('#') { + let trimmed_line = line.trim_whitespace_start(); + if trimmed_line.is_empty() { + continue; + } + if trimmed_line.starts_with('#') { location = line.full_end(); } else { break; @@ -137,6 +141,7 @@ impl<'a> Insertion<'a> { mut location: TextSize, locator: &Locator<'a>, stylist: &Stylist, + source_type: PySourceType, ) -> Insertion<'a> { enum Awaiting { Colon(u32), @@ -146,7 +151,7 @@ impl<'a> Insertion<'a> { let mut state = Awaiting::Colon(0); for (tok, range) in - lexer::lex_starts_at(locator.after(location), Mode::Module, location).flatten() + lexer::lex_starts_at(locator.after(location), source_type.as_mode(), location).flatten() { match state { // Iterate until we find the colon indicating the start of the block body. @@ -299,21 +304,21 @@ fn match_leading_semicolon(s: &str) -> Option { #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::Suite; - use ruff_python_parser::lexer::LexResult; - use ruff_python_parser::Parse; - use ruff_text_size::TextSize; + use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; + use ruff_python_parser::lexer::LexResult; + use ruff_python_parser::{parse_suite, Mode}; use ruff_source_file::{LineEnding, Locator}; + use ruff_text_size::TextSize; use super::Insertion; #[test] fn start_of_file() -> Result<()> { fn insert(contents: &str) -> Result { - let program = Suite::parse(contents, "")?; - let tokens: Vec = ruff_python_parser::tokenize(contents); + let program = parse_suite(contents, "")?; + let tokens: Vec = ruff_python_parser::tokenize(contents, Mode::Module); let locator = Locator::new(contents); let stylist = Stylist::from_tokens(&tokens, &locator); Ok(Insertion::start_of_file(&program, &locator, &stylist)) @@ -424,10 +429,10 @@ x = 1 #[test] fn start_of_block() { fn insert(contents: &str, offset: TextSize) -> Insertion { - let tokens: Vec = ruff_python_parser::tokenize(contents); + let tokens: Vec = ruff_python_parser::tokenize(contents, Mode::Module); let locator = Locator::new(contents); let stylist = Stylist::from_tokens(&tokens, &locator); - Insertion::start_of_block(offset, &locator, &stylist) + Insertion::start_of_block(offset, &locator, &stylist, PySourceType::default()) } let contents = "if True: pass"; diff --git a/crates/ruff/src/importer/mod.rs b/crates/ruff/src/importer/mod.rs index 12de3f2702df7..ed4e3d6728c82 100644 --- a/crates/ruff/src/importer/mod.rs +++ b/crates/ruff/src/importer/mod.rs @@ -7,7 +7,7 @@ use std::error::Error; use anyhow::Result; use libcst_native::{ImportAlias, Name, NameOrAttribute}; -use ruff_python_ast::{self as ast, Ranged, Stmt, Suite}; +use ruff_python_ast::{self as ast, PySourceType, Ranged, Stmt, Suite}; use ruff_text_size::TextSize; use ruff_diagnostics::Edit; @@ -87,13 +87,13 @@ impl<'a> Importer<'a> { /// import statement. pub(crate) fn runtime_import_edit( &self, - import: &StmtImports, + import: &ImportedMembers, at: TextSize, ) -> Result { // Generate the modified import statement. let content = autofix::codemods::retain_imports( - &import.qualified_names, - import.stmt, + &import.names, + import.statement, self.locator, self.stylist, )?; @@ -118,14 +118,15 @@ impl<'a> Importer<'a> { /// `TYPE_CHECKING` block. pub(crate) fn typing_import_edit( &self, - import: &StmtImports, + import: &ImportedMembers, at: TextSize, semantic: &SemanticModel, + source_type: PySourceType, ) -> Result { // Generate the modified import statement. let content = autofix::codemods::retain_imports( - &import.qualified_names, - import.stmt, + &import.names, + import.statement, self.locator, self.stylist, )?; @@ -140,7 +141,7 @@ impl<'a> Importer<'a> { // Add the import to a `TYPE_CHECKING` block. let add_import_edit = if let Some(block) = self.preceding_type_checking_block(at) { // Add the import to the `TYPE_CHECKING` block. - self.add_to_type_checking_block(&content, block.start()) + self.add_to_type_checking_block(&content, block.start(), source_type) } else { // Add the import to a new `TYPE_CHECKING` block. self.add_type_checking_block( @@ -193,7 +194,7 @@ impl<'a> Importer<'a> { // import and the current location, and thus the symbol would not be available). It's also // unclear whether should add an import statement at the start of the file, since it could // be shadowed between the import and the current location. - if imported_name.range().start() > at { + if imported_name.start() > at { return Some(Err(ResolutionError::ImportAfterUsage)); } @@ -300,12 +301,14 @@ impl<'a> Importer<'a> { } if let Stmt::ImportFrom(ast::StmtImportFrom { module: name, + names, level, - .. + range: _, }) = stmt { if level.map_or(true, |level| level.to_u32() == 0) - && name.as_ref().map_or(false, |name| name == module) + && name.as_ref().is_some_and(|name| name == module) + && names.iter().all(|alias| alias.name.as_str() != "*") { import_from = Some(*stmt); } @@ -353,8 +356,13 @@ impl<'a> Importer<'a> { } /// Add an import statement to an existing `TYPE_CHECKING` block. - fn add_to_type_checking_block(&self, content: &str, at: TextSize) -> Edit { - Insertion::start_of_block(at, self.locator, self.stylist).into_edit(content) + fn add_to_type_checking_block( + &self, + content: &str, + at: TextSize, + source_type: PySourceType, + ) -> Edit { + Insertion::start_of_block(at, self.locator, self.stylist, source_type).into_edit(content) } /// Return the import statement that precedes the given position, if any. @@ -446,11 +454,11 @@ impl<'a> ImportRequest<'a> { } /// An existing list of module or member imports, located within an import statement. -pub(crate) struct StmtImports<'a> { +pub(crate) struct ImportedMembers<'a> { /// The import statement. - pub(crate) stmt: &'a Stmt, - /// The "qualified names" of the imported modules or members. - pub(crate) qualified_names: Vec<&'a str>, + pub(crate) statement: &'a Stmt, + /// The "names" of the imported members. + pub(crate) names: Vec<&'a str>, } /// The result of an [`Importer::get_or_import_symbol`] call. diff --git a/crates/ruff/src/jupyter/index.rs b/crates/ruff/src/jupyter/index.rs index 6a46d4da315c4..f5150d01f7ddb 100644 --- a/crates/ruff/src/jupyter/index.rs +++ b/crates/ruff/src/jupyter/index.rs @@ -3,14 +3,14 @@ /// When we lint a jupyter notebook, we have to translate the row/column based on /// [`ruff_text_size::TextSize`] to jupyter notebook cell/row/column. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct JupyterIndex { +pub struct NotebookIndex { /// Enter a row (1-based), get back the cell (1-based) pub(super) row_to_cell: Vec, /// Enter a row (1-based), get back the row in cell (1-based) pub(super) row_to_row_in_cell: Vec, } -impl JupyterIndex { +impl NotebookIndex { /// Returns the cell number (1-based) for the given row (1-based). pub fn cell(&self, row: usize) -> Option { self.row_to_cell.get(row).copied() diff --git a/crates/ruff/src/jupyter/notebook.rs b/crates/ruff/src/jupyter/notebook.rs index 37d372a65d5f1..f36ce19171f34 100644 --- a/crates/ruff/src/jupyter/notebook.rs +++ b/crates/ruff/src/jupyter/notebook.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::fmt::Display; use std::fs::File; -use std::io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}; +use std::io::{BufReader, BufWriter, Cursor, Read, Seek, SeekFrom, Write}; use std::iter; use std::path::Path; @@ -9,6 +9,7 @@ use itertools::Itertools; use once_cell::sync::OnceCell; use serde::Serialize; use serde_json::error::Category; +use uuid::Uuid; use ruff_diagnostics::Diagnostic; use ruff_python_parser::lexer::lex; @@ -17,25 +18,23 @@ use ruff_source_file::{NewlineWithTrailingNewline, UniversalNewlineIterator}; use ruff_text_size::{TextRange, TextSize}; use crate::autofix::source_map::{SourceMap, SourceMarker}; -use crate::jupyter::index::JupyterIndex; +use crate::jupyter::index::NotebookIndex; use crate::jupyter::schema::{Cell, RawNotebook, SortAlphabetically, SourceValue}; use crate::rules::pycodestyle::rules::SyntaxError; use crate::IOError; pub const JUPYTER_NOTEBOOK_EXT: &str = "ipynb"; -const MAGIC_PREFIX: [&str; 3] = ["%", "!", "?"]; - /// Run round-trip source code generation on a given Jupyter notebook file path. pub fn round_trip(path: &Path) -> anyhow::Result { - let mut notebook = Notebook::read(path).map_err(|err| { + let mut notebook = Notebook::from_path(path).map_err(|err| { anyhow::anyhow!( "Failed to read notebook file `{}`: {:?}", path.display(), err ) })?; - let code = notebook.content().to_string(); + let code = notebook.source_code().to_string(); notebook.update_cell_content(&code); let mut writer = Vec::new(); notebook.write_inner(&mut writer)?; @@ -78,26 +77,21 @@ impl Cell { /// Return `true` if it's a valid code cell. /// /// A valid code cell is a cell where the cell type is [`Cell::Code`] and the - /// source doesn't contain a magic, shell or help command. + /// source doesn't contain a cell magic. fn is_valid_code_cell(&self) -> bool { let source = match self { Cell::Code(cell) => &cell.source, _ => return false, }; - // Ignore a cell if it contains a magic command. There could be valid - // Python code as well, but we'll ignore that for now. - // TODO(dhruvmanila): https://github.com/psf/black/blob/main/src/black/handle_ipynb_magics.py + // Ignore cells containing cell magic as they act on the entire cell + // as compared to line magic which acts on a single line. !match source { - SourceValue::String(string) => string.lines().any(|line| { - MAGIC_PREFIX - .iter() - .any(|prefix| line.trim_start().starts_with(prefix)) - }), - SourceValue::StringArray(string_array) => string_array.iter().any(|line| { - MAGIC_PREFIX - .iter() - .any(|prefix| line.trim_start().starts_with(prefix)) - }), + SourceValue::String(string) => string + .lines() + .any(|line| line.trim_start().starts_with("%%")), + SourceValue::StringArray(string_array) => string_array + .iter() + .any(|line| line.trim_start().starts_with("%%")), } } } @@ -110,10 +104,10 @@ pub struct Notebook { /// separated by a newline and a trailing newline. The trailing newline /// is added to make sure that each cell ends with a newline which will /// be removed when updating the cell content. - content: String, + source_code: String, /// The index of the notebook. This is used to map between the concatenated /// source code and the original notebook. - index: OnceCell, + index: OnceCell, /// The raw notebook i.e., the deserialized version of JSON string. raw: RawNotebook, /// The offsets of each cell in the concatenated source code. This includes @@ -127,18 +121,30 @@ pub struct Notebook { impl Notebook { /// Read the Jupyter Notebook from the given [`Path`]. - /// - /// See also the black implementation - /// - pub fn read(path: &Path) -> Result> { - let mut reader = BufReader::new(File::open(path).map_err(|err| { + pub fn from_path(path: &Path) -> Result> { + Self::from_reader(BufReader::new(File::open(path).map_err(|err| { Diagnostic::new( IOError { message: format!("{err}"), }, TextRange::default(), ) - })?); + })?)) + } + + /// Read the Jupyter Notebook from its JSON string. + pub fn from_source_code(source_code: &str) -> Result> { + Self::from_reader(Cursor::new(source_code)) + } + + /// Read a Jupyter Notebook from a [`Read`] implementor. + /// + /// See also the black implementation + /// + fn from_reader(mut reader: R) -> Result> + where + R: Read + Seek, + { let trailing_newline = reader.seek(SeekFrom::End(-1)).is_ok_and(|_| { let mut buf = [0; 1]; reader.read_exact(&mut buf).is_ok_and(|_| buf[0] == b'\n') @@ -151,7 +157,7 @@ impl Notebook { TextRange::default(), ) })?; - let raw_notebook: RawNotebook = match serde_json::from_reader(reader) { + let mut raw_notebook: RawNotebook = match serde_json::from_reader(reader.by_ref()) { Ok(notebook) => notebook, Err(err) => { // Translate the error into a diagnostic @@ -166,14 +172,19 @@ impl Notebook { Category::Syntax | Category::Eof => { // Maybe someone saved the python sources (those with the `# %%` separator) // as jupyter notebook instead. Let's help them. - let contents = std::fs::read_to_string(path).map_err(|err| { - Diagnostic::new( - IOError { - message: format!("{err}"), - }, - TextRange::default(), - ) - })?; + let mut contents = String::new(); + reader + .rewind() + .and_then(|_| reader.read_to_string(&mut contents)) + .map_err(|err| { + Diagnostic::new( + IOError { + message: format!("{err}"), + }, + TextRange::default(), + ) + })?; + // Check if tokenizing was successful and the file is non-empty if lex(&contents, Mode::Module).any(|result| result.is_err()) { Diagnostic::new( @@ -189,7 +200,7 @@ impl Notebook { Diagnostic::new( SyntaxError { message: format!( - "Expected a Jupyter Notebook (.{JUPYTER_NOTEBOOK_EXT} extension), \ + "Expected a Jupyter Notebook (.{JUPYTER_NOTEBOOK_EXT}), \ which must be internally stored as JSON, \ but found a Python source file: {err}" ), @@ -252,13 +263,30 @@ impl Notebook { cell_offsets.push(current_offset); } + // Add cell ids to 4.5+ notebooks if they are missing + // https://github.com/astral-sh/ruff/issues/6834 + // https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md#required-field + if raw_notebook.nbformat == 4 && raw_notebook.nbformat_minor >= 5 { + for cell in &mut raw_notebook.cells { + let id = match cell { + Cell::Code(cell) => &mut cell.id, + Cell::Markdown(cell) => &mut cell.id, + Cell::Raw(cell) => &mut cell.id, + }; + if id.is_none() { + // https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md#questions + *id = Some(Uuid::new_v4().to_string()); + } + } + } + Ok(Self { raw: raw_notebook, index: OnceCell::new(), // The additional newline at the end is to maintain consistency for // all cells. These newlines will be removed before updating the // source code with the transformed content. Refer `update_cell_content`. - content: contents.join("\n") + "\n", + source_code: contents.join("\n") + "\n", cell_offsets, valid_code_cells, trailing_newline, @@ -358,7 +386,7 @@ impl Notebook { /// /// The index building is expensive as it needs to go through the content of /// every valid code cell. - fn build_index(&self) -> JupyterIndex { + fn build_index(&self) -> NotebookIndex { let mut row_to_cell = vec![0]; let mut row_to_row_in_cell = vec![0]; @@ -376,7 +404,7 @@ impl Notebook { 1 } else { let trailing_newline = - usize::from(string_array.last().map_or(false, |s| s.ends_with('\n'))); + usize::from(string_array.last().is_some_and(|s| s.ends_with('\n'))); u32::try_from(string_array.len() + trailing_newline).unwrap() } } @@ -385,7 +413,7 @@ impl Notebook { row_to_row_in_cell.extend(1..=line_count); } - JupyterIndex { + NotebookIndex { row_to_cell, row_to_row_in_cell, } @@ -394,8 +422,8 @@ impl Notebook { /// Return the notebook content. /// /// This is the concatenation of all Python code cells. - pub(crate) fn content(&self) -> &str { - &self.content + pub fn source_code(&self) -> &str { + &self.source_code } /// Return the Jupyter notebook index. @@ -403,7 +431,7 @@ impl Notebook { /// The index is built only once when required. This is only used to /// report diagnostics, so by that time all of the autofixes must have /// been applied if `--fix` was passed. - pub(crate) fn index(&self) -> &JupyterIndex { + pub(crate) fn index(&self) -> &NotebookIndex { self.index.get_or_init(|| self.build_index()) } @@ -414,12 +442,13 @@ impl Notebook { } /// Update the notebook with the given sourcemap and transformed content. - pub(crate) fn update(&mut self, source_map: &SourceMap, transformed: &str) { + pub(crate) fn update(&mut self, source_map: &SourceMap, transformed: String) { // Cell offsets must be updated before updating the cell content as // it depends on the offsets to extract the cell content. + self.index.take(); self.update_cell_offsets(source_map); - self.update_cell_content(transformed); - self.content = transformed.to_string(); + self.update_cell_content(&transformed); + self.source_code = transformed; } /// Return a slice of [`Cell`] in the Jupyter notebook. @@ -462,18 +491,22 @@ mod tests { use anyhow::Result; use test_case::test_case; - use crate::jupyter::index::JupyterIndex; + use crate::jupyter::index::NotebookIndex; use crate::jupyter::schema::Cell; use crate::jupyter::Notebook; use crate::registry::Rule; - use crate::test::{read_jupyter_notebook, test_notebook_path, test_resource_path}; + use crate::source_kind::SourceKind; + use crate::test::{ + read_jupyter_notebook, test_contents, test_notebook_path, test_resource_path, + TestedNotebook, + }; use crate::{assert_messages, settings}; /// Read a Jupyter cell from the `resources/test/fixtures/jupyter/cell` directory. fn read_jupyter_cell(path: impl AsRef) -> Result { let path = test_resource_path("fixtures/jupyter/cell").join(path); - let contents = std::fs::read_to_string(path)?; - Ok(serde_json::from_str(&contents)?) + let source_code = std::fs::read_to_string(path)?; + Ok(serde_json::from_str(&source_code)?) } #[test] @@ -491,31 +524,32 @@ mod tests { fn test_invalid() { let path = Path::new("resources/test/fixtures/jupyter/invalid_extension.ipynb"); assert_eq!( - Notebook::read(path).unwrap_err().kind.body, - "SyntaxError: Expected a Jupyter Notebook (.ipynb extension), \ + Notebook::from_path(path).unwrap_err().kind.body, + "SyntaxError: Expected a Jupyter Notebook (.ipynb), \ which must be internally stored as JSON, \ but found a Python source file: \ expected value at line 1 column 1" ); let path = Path::new("resources/test/fixtures/jupyter/not_json.ipynb"); assert_eq!( - Notebook::read(path).unwrap_err().kind.body, + Notebook::from_path(path).unwrap_err().kind.body, "SyntaxError: A Jupyter Notebook (.ipynb) must internally be JSON, \ but this file isn't valid JSON: \ expected value at line 1 column 1" ); let path = Path::new("resources/test/fixtures/jupyter/wrong_schema.ipynb"); assert_eq!( - Notebook::read(path).unwrap_err().kind.body, + Notebook::from_path(path).unwrap_err().kind.body, "SyntaxError: This file does not match the schema expected of Jupyter Notebooks: \ missing field `cells` at line 1 column 2" ); } #[test_case(Path::new("markdown.json"), false; "markdown")] - #[test_case(Path::new("only_magic.json"), false; "only_magic")] - #[test_case(Path::new("code_and_magic.json"), false; "code_and_magic")] + #[test_case(Path::new("only_magic.json"), true; "only_magic")] + #[test_case(Path::new("code_and_magic.json"), true; "code_and_magic")] #[test_case(Path::new("only_code.json"), true; "only_code")] + #[test_case(Path::new("cell_magic.json"), false; "cell_magic")] fn test_is_valid_code_cell(path: &Path, expected: bool) -> Result<()> { assert_eq!(read_jupyter_cell(path)?.is_valid_code_cell(), expected); Ok(()) @@ -525,7 +559,7 @@ mod tests { fn test_concat_notebook() -> Result<()> { let notebook = read_jupyter_notebook(Path::new("valid.ipynb"))?; assert_eq!( - notebook.content, + notebook.source_code, r#"def unused_variable(): x = 1 y = 2 @@ -545,7 +579,7 @@ print("after empty cells") ); assert_eq!( notebook.index(), - &JupyterIndex { + &NotebookIndex { row_to_cell: vec![0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 5, 7, 7, 8], row_to_row_in_cell: vec![0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 1, 1, 2, 1], } @@ -567,25 +601,64 @@ print("after empty cells") #[test] fn test_import_sorting() -> Result<()> { let path = "isort.ipynb".to_string(); - let (diagnostics, source_kind) = test_notebook_path( + let TestedNotebook { + messages, + source_notebook, + .. + } = test_notebook_path( &path, Path::new("isort_expected.ipynb"), &settings::Settings::for_rule(Rule::UnsortedImports), )?; - assert_messages!(diagnostics, path, source_kind); + assert_messages!(messages, path, source_notebook); + Ok(()) + } + + #[test] + fn test_ipy_escape_command() -> Result<()> { + let path = "ipy_escape_command.ipynb".to_string(); + let TestedNotebook { + messages, + source_notebook, + .. + } = test_notebook_path( + &path, + Path::new("ipy_escape_command_expected.ipynb"), + &settings::Settings::for_rule(Rule::UnusedImport), + )?; + assert_messages!(messages, path, source_notebook); + Ok(()) + } + + #[test] + fn test_unused_variable() -> Result<()> { + let path = "unused_variable.ipynb".to_string(); + let TestedNotebook { + messages, + source_notebook, + .. + } = test_notebook_path( + &path, + Path::new("unused_variable_expected.ipynb"), + &settings::Settings::for_rule(Rule::UnusedVariable), + )?; + assert_messages!(messages, path, source_notebook); Ok(()) } #[test] fn test_json_consistency() -> Result<()> { let path = "before_fix.ipynb".to_string(); - let (_, source_kind) = test_notebook_path( + let TestedNotebook { + linted_notebook: fixed_notebook, + .. + } = test_notebook_path( path, Path::new("after_fix.ipynb"), &settings::Settings::for_rule(Rule::UnusedImport), )?; let mut writer = Vec::new(); - source_kind.expect_jupyter().write_inner(&mut writer)?; + fixed_notebook.write_inner(&mut writer)?; let actual = String::from_utf8(writer)?; let expected = std::fs::read_to_string(test_resource_path("fixtures/jupyter/after_fix.ipynb"))?; @@ -606,4 +679,28 @@ print("after empty cells") Ok(()) } + + // Version <4.5, don't emit cell ids + #[test_case(Path::new("no_cell_id.ipynb"), false; "no_cell_id")] + // Version 4.5, cell ids are missing and need to be added + #[test_case(Path::new("add_missing_cell_id.ipynb"), true; "add_missing_cell_id")] + fn test_cell_id(path: &Path, has_id: bool) -> Result<()> { + let source_notebook = read_jupyter_notebook(path)?; + let source_kind = SourceKind::IpyNotebook(source_notebook); + let (_, transformed) = test_contents( + &source_kind, + path, + &settings::Settings::for_rule(Rule::UnusedImport), + ); + let linted_notebook = transformed.into_owned().expect_ipy_notebook(); + let mut writer = Vec::new(); + linted_notebook.write_inner(&mut writer)?; + let actual = String::from_utf8(writer)?; + if has_id { + assert!(actual.contains(r#""id": ""#)); + } else { + assert!(!actual.contains(r#""id":"#)); + } + Ok(()) + } } diff --git a/crates/ruff/src/jupyter/schema.rs b/crates/ruff/src/jupyter/schema.rs index b6f9ed3c47134..e466615feca52 100644 --- a/crates/ruff/src/jupyter/schema.rs +++ b/crates/ruff/src/jupyter/schema.rs @@ -150,6 +150,7 @@ pub struct CodeCell { /// Technically, id isn't required (it's not even present) in schema v4.0 through v4.4, but /// it's required in v4.5. Main issue is that pycharm creates notebooks without an id /// + #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, /// Cell-level metadata. pub metadata: Value, diff --git a/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__import_sorting.snap b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__import_sorting.snap index 240556c37576f..e0ab3572a84d4 100644 --- a/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__import_sorting.snap +++ b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__import_sorting.snap @@ -47,4 +47,43 @@ isort.ipynb:cell 2:1:1: I001 [*] Import block is un-sorted or un-formatted 7 9 | def foo(): 8 10 | pass +isort.ipynb:cell 3:1:1: I001 [*] Import block is un-sorted or un-formatted + | +1 | / from pathlib import Path +2 | | import sys +3 | | +4 | | %matplotlib \ + | |_^ I001 +5 | --inline + | + = help: Organize imports + +ℹ Fix +6 6 | # Newline should be added here +7 7 | def foo(): +8 8 | pass + 9 |+import sys +9 10 | from pathlib import Path +10 |-import sys +11 11 | +12 12 | %matplotlib \ +13 13 | --inline + +isort.ipynb:cell 3:7:1: I001 [*] Import block is un-sorted or un-formatted + | +5 | --inline +6 | +7 | / import math +8 | | import abc + | + = help: Organize imports + +ℹ Fix +12 12 | %matplotlib \ +13 13 | --inline +14 14 | + 15 |+import abc +15 16 | import math +16 |-import abc + diff --git a/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__ipy_escape_command.snap b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__ipy_escape_command.snap new file mode 100644 index 0000000000000..57f92d184e1d1 --- /dev/null +++ b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__ipy_escape_command.snap @@ -0,0 +1,23 @@ +--- +source: crates/ruff/src/jupyter/notebook.rs +--- +ipy_escape_command.ipynb:cell 1:5:8: F401 [*] `os` imported but unused + | +3 | %matplotlib inline +4 | +5 | import os + | ^^ F401 +6 | +7 | _ = math.pi + | + = help: Remove unused import: `os` + +ℹ Fix +2 2 | +3 3 | %matplotlib inline +4 4 | +5 |-import os +6 5 | +7 6 | _ = math.pi + + diff --git a/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__unused_variable.snap b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__unused_variable.snap new file mode 100644 index 0000000000000..689e20e25ee18 --- /dev/null +++ b/crates/ruff/src/jupyter/snapshots/ruff__jupyter__notebook__tests__unused_variable.snap @@ -0,0 +1,72 @@ +--- +source: crates/ruff/src/jupyter/notebook.rs +--- +unused_variable.ipynb:cell 1:2:5: F841 [*] Local variable `foo1` is assigned to but never used + | +1 | def f(): +2 | foo1 = %matplotlib --list + | ^^^^ F841 +3 | foo2: list[str] = %matplotlib --list + | + = help: Remove assignment to unused variable `foo1` + +ℹ Suggested fix +1 1 | def f(): +2 |- foo1 = %matplotlib --list + 2 |+ %matplotlib --list +3 3 | foo2: list[str] = %matplotlib --list +4 4 | def f(): +5 5 | bar1 = !pwd + +unused_variable.ipynb:cell 1:3:5: F841 [*] Local variable `foo2` is assigned to but never used + | +1 | def f(): +2 | foo1 = %matplotlib --list +3 | foo2: list[str] = %matplotlib --list + | ^^^^ F841 + | + = help: Remove assignment to unused variable `foo2` + +ℹ Suggested fix +1 1 | def f(): +2 2 | foo1 = %matplotlib --list +3 |- foo2: list[str] = %matplotlib --list + 3 |+ %matplotlib --list +4 4 | def f(): +5 5 | bar1 = !pwd +6 6 | bar2: str = !pwd + +unused_variable.ipynb:cell 2:2:5: F841 [*] Local variable `bar1` is assigned to but never used + | +1 | def f(): +2 | bar1 = !pwd + | ^^^^ F841 +3 | bar2: str = !pwd + | + = help: Remove assignment to unused variable `bar1` + +ℹ Suggested fix +2 2 | foo1 = %matplotlib --list +3 3 | foo2: list[str] = %matplotlib --list +4 4 | def f(): +5 |- bar1 = !pwd + 5 |+ !pwd +6 6 | bar2: str = !pwd + +unused_variable.ipynb:cell 2:3:5: F841 [*] Local variable `bar2` is assigned to but never used + | +1 | def f(): +2 | bar1 = !pwd +3 | bar2: str = !pwd + | ^^^^ F841 + | + = help: Remove assignment to unused variable `bar2` + +ℹ Suggested fix +3 3 | foo2: list[str] = %matplotlib --list +4 4 | def f(): +5 5 | bar1 = !pwd +6 |- bar2: str = !pwd + 6 |+ !pwd + + diff --git a/crates/ruff/src/line_width.rs b/crates/ruff/src/line_width.rs index 8619b42aa36ac..ee8e4f6bc9561 100644 --- a/crates/ruff/src/line_width.rs +++ b/crates/ruff/src/line_width.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::num::NonZeroU8; use unicode_width::UnicodeWidthChar; use ruff_macros::CacheKey; @@ -58,7 +59,7 @@ impl Eq for LineWidth {} impl PartialOrd for LineWidth { fn partial_cmp(&self, other: &Self) -> Option { - self.width.partial_cmp(&other.width) + Some(self.cmp(other)) } } @@ -83,7 +84,7 @@ impl LineWidth { } fn update(mut self, chars: impl Iterator) -> Self { - let tab_size: usize = self.tab_size.into(); + let tab_size: usize = self.tab_size.as_usize(); for c in chars { match c { '\t' => { @@ -144,22 +145,22 @@ impl PartialOrd for LineWidth { /// The size of a tab. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, CacheKey)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct TabSize(pub u8); +pub struct TabSize(NonZeroU8); -impl Default for TabSize { - fn default() -> Self { - Self(4) +impl TabSize { + pub(crate) fn as_usize(self) -> usize { + self.0.get() as usize } } -impl From for TabSize { - fn from(tab_size: u8) -> Self { - Self(tab_size) +impl Default for TabSize { + fn default() -> Self { + Self(NonZeroU8::new(4).unwrap()) } } -impl From for usize { - fn from(tab_size: TabSize) -> Self { - tab_size.0 as usize +impl From for TabSize { + fn from(tab_size: NonZeroU8) -> Self { + Self(tab_size) } } diff --git a/crates/ruff/src/linter.rs b/crates/ruff/src/linter.rs index 0f614535da42a..98316154836e8 100644 --- a/crates/ruff/src/linter.rs +++ b/crates/ruff/src/linter.rs @@ -7,14 +7,15 @@ use colored::Colorize; use itertools::Itertools; use log::error; use ruff_python_parser::lexer::LexResult; -use ruff_python_parser::ParseError; +use ruff_python_parser::{AsMode, ParseError}; use rustc_hash::FxHashMap; use ruff_diagnostics::Diagnostic; use ruff_python_ast::imports::ImportMap; +use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; -use ruff_python_stdlib::path::is_python_stub_file; + use ruff_source_file::{Locator, SourceFileBuilder}; use crate::autofix::{fix_file, FixResult}; @@ -62,7 +63,7 @@ pub struct FixerResult<'a> { /// The result returned by the linter, after applying any fixes. pub result: LinterResult<(Vec, Option)>, /// The resulting source code, after applying any fixes. - pub transformed: Cow<'a, str>, + pub transformed: Cow<'a, SourceKind>, /// The number of fixes applied for each [`Rule`]. pub fixed: FixTable, } @@ -81,6 +82,7 @@ pub fn check_path( settings: &Settings, noqa: flags::Noqa, source_kind: Option<&SourceKind>, + source_type: PySourceType, ) -> LinterResult<(Vec, Option)> { // Aggregate all diagnostics. let mut diagnostics = vec![]; @@ -101,9 +103,13 @@ pub fn check_path( .iter_enabled() .any(|rule_code| rule_code.lint_source().is_tokens()) { - let is_stub = is_python_stub_file(path); diagnostics.extend(check_tokens( - &tokens, path, locator, indexer, settings, is_stub, + &tokens, + path, + locator, + indexer, + settings, + source_type.is_stub(), )); } @@ -138,7 +144,11 @@ pub fn check_path( .iter_enabled() .any(|rule_code| rule_code.lint_source().is_imports()); if use_ast || use_imports || use_doc_lines { - match ruff_python_parser::parse_program_tokens(tokens, &path.to_string_lossy()) { + match ruff_python_parser::parse_program_tokens( + tokens, + &path.to_string_lossy(), + source_type.is_ipynb(), + ) { Ok(python_ast) => { if use_ast { diagnostics.extend(check_ast( @@ -151,6 +161,7 @@ pub fn check_path( noqa, path, package, + source_type, )); } if use_imports { @@ -164,6 +175,7 @@ pub fn check_path( path, package, source_kind, + source_type, ); imports = module_imports; diagnostics.extend(import_diagnostics); @@ -256,11 +268,13 @@ const MAX_ITERATIONS: usize = 100; /// Add any missing `# noqa` pragmas to the source code at the given `Path`. pub fn add_noqa_to_path(path: &Path, package: Option<&Path>, settings: &Settings) -> Result { + let source_type = PySourceType::from(path); + // Read the file from disk. let contents = std::fs::read_to_string(path)?; // Tokenize once. - let tokens: Vec = ruff_python_parser::tokenize(&contents); + let tokens: Vec = ruff_python_parser::tokenize(&contents, source_type.as_mode()); // Map row and column locations to byte slices (lazily). let locator = Locator::new(&contents); @@ -294,6 +308,7 @@ pub fn add_noqa_to_path(path: &Path, package: Option<&Path>, settings: &Settings settings, flags::Noqa::Disabled, None, + source_type, ); // Log any parse errors. @@ -320,18 +335,19 @@ pub fn add_noqa_to_path(path: &Path, package: Option<&Path>, settings: &Settings /// Generate a [`Message`] for each [`Diagnostic`] triggered by the given source /// code. pub fn lint_only( - contents: &str, path: &Path, package: Option<&Path>, settings: &Settings, noqa: flags::Noqa, - source_kind: Option<&SourceKind>, + source_kind: &SourceKind, + source_type: PySourceType, ) -> LinterResult<(Vec, Option)> { // Tokenize once. - let tokens: Vec = ruff_python_parser::tokenize(contents); + let tokens: Vec = + ruff_python_parser::tokenize(source_kind.source_code(), source_type.as_mode()); // Map row and column locations to byte slices (lazily). - let locator = Locator::new(contents); + let locator = Locator::new(source_kind.source_code()); // Detect the current code style (lazily). let stylist = Stylist::from_tokens(&tokens, &locator); @@ -358,7 +374,8 @@ pub fn lint_only( &directives, settings, noqa, - source_kind, + Some(source_kind), + source_type, ); result.map(|(diagnostics, imports)| { @@ -399,14 +416,14 @@ fn diagnostics_to_messages( /// Generate `Diagnostic`s from source code content, iteratively autofixing /// until stable. pub fn lint_fix<'a>( - contents: &'a str, path: &Path, package: Option<&Path>, noqa: flags::Noqa, settings: &Settings, - source_kind: &mut SourceKind, + source_kind: &'a SourceKind, + source_type: PySourceType, ) -> Result> { - let mut transformed = Cow::Borrowed(contents); + let mut transformed = Cow::Borrowed(source_kind); // Track the number of fixed errors across iterations. let mut fixed = FxHashMap::default(); @@ -420,10 +437,11 @@ pub fn lint_fix<'a>( // Continuously autofix until the source code stabilizes. loop { // Tokenize once. - let tokens: Vec = ruff_python_parser::tokenize(&transformed); + let tokens: Vec = + ruff_python_parser::tokenize(transformed.source_code(), source_type.as_mode()); // Map row and column locations to byte slices (lazily). - let locator = Locator::new(&transformed); + let locator = Locator::new(transformed.source_code()); // Detect the current code style (lazily). let stylist = Stylist::from_tokens(&tokens, &locator); @@ -451,6 +469,7 @@ pub fn lint_fix<'a>( settings, noqa, Some(source_kind), + source_type, ); if iterations == 0 { @@ -462,7 +481,7 @@ pub fn lint_fix<'a>( if parseable && result.error.is_some() { report_autofix_syntax_error( path, - &transformed, + transformed.source_code(), &result.error.unwrap(), fixed.keys().copied(), ); @@ -483,12 +502,7 @@ pub fn lint_fix<'a>( *fixed.entry(rule).or_default() += count; } - if let SourceKind::Jupyter(notebook) = source_kind { - notebook.update(&source_map, &fixed_contents); - } - - // Store the fixed contents. - transformed = Cow::Owned(fixed_contents); + transformed = Cow::Owned(transformed.updated(fixed_contents, &source_map)); // Increment the iteration count. iterations += 1; @@ -497,7 +511,7 @@ pub fn lint_fix<'a>( continue; } - report_failed_to_converge_error(path, &transformed, &result.data.0); + report_failed_to_converge_error(path, transformed.source_code(), &result.data.0); } return Ok(FixerResult { diff --git a/crates/ruff/src/message/azure.rs b/crates/ruff/src/message/azure.rs index a95a7ea21707e..76245ca16dda4 100644 --- a/crates/ruff/src/message/azure.rs +++ b/crates/ruff/src/message/azure.rs @@ -18,7 +18,7 @@ impl Emitter for AzureEmitter { context: &EmitterContext, ) -> anyhow::Result<()> { for message in messages { - let location = if context.is_jupyter_notebook(message.filename()) { + let location = if context.is_notebook(message.filename()) { // We can't give a reasonable location for the structured formats, // so we show one that's clearly a fallback SourceLocation::default() diff --git a/crates/ruff/src/message/github.rs b/crates/ruff/src/message/github.rs index 86e8c23feaecf..7ce6dee159415 100644 --- a/crates/ruff/src/message/github.rs +++ b/crates/ruff/src/message/github.rs @@ -20,7 +20,7 @@ impl Emitter for GithubEmitter { ) -> anyhow::Result<()> { for message in messages { let source_location = message.compute_start_location(); - let location = if context.is_jupyter_notebook(message.filename()) { + let location = if context.is_notebook(message.filename()) { // We can't give a reasonable location for the structured formats, // so we show one that's clearly a fallback SourceLocation::default() diff --git a/crates/ruff/src/message/gitlab.rs b/crates/ruff/src/message/gitlab.rs index 00720fbc54d40..e799823fda827 100644 --- a/crates/ruff/src/message/gitlab.rs +++ b/crates/ruff/src/message/gitlab.rs @@ -63,7 +63,7 @@ impl Serialize for SerializedMessages<'_> { let start_location = message.compute_start_location(); let end_location = message.compute_end_location(); - let lines = if self.context.is_jupyter_notebook(message.filename()) { + let lines = if self.context.is_notebook(message.filename()) { // We can't give a reasonable location for the structured formats, // so we show one that's clearly a fallback json!({ diff --git a/crates/ruff/src/message/grouped.rs b/crates/ruff/src/message/grouped.rs index 417a39e33cdb1..467a5b54665f9 100644 --- a/crates/ruff/src/message/grouped.rs +++ b/crates/ruff/src/message/grouped.rs @@ -7,13 +7,12 @@ use colored::Colorize; use ruff_source_file::OneIndexed; use crate::fs::relativize_path; -use crate::jupyter::{JupyterIndex, Notebook}; +use crate::jupyter::{Notebook, NotebookIndex}; use crate::message::diff::calculate_print_width; use crate::message::text::{MessageCodeFrame, RuleCodeAndBody}; use crate::message::{ group_messages_by_filename, Emitter, EmitterContext, Message, MessageWithLocation, }; -use crate::source_kind::SourceKind; #[derive(Default)] pub struct GroupedEmitter { @@ -66,10 +65,7 @@ impl Emitter for GroupedEmitter { writer, "{}", DisplayGroupedMessage { - jupyter_index: context - .source_kind(message.filename()) - .and_then(SourceKind::notebook) - .map(Notebook::index), + jupyter_index: context.notebook(message.filename()).map(Notebook::index), message, show_fix_status: self.show_fix_status, show_source: self.show_source, @@ -96,7 +92,7 @@ struct DisplayGroupedMessage<'a> { show_source: bool, row_length: NonZeroUsize, column_length: NonZeroUsize, - jupyter_index: Option<&'a JupyterIndex>, + jupyter_index: Option<&'a NotebookIndex>, } impl Display for DisplayGroupedMessage<'_> { diff --git a/crates/ruff/src/message/junit.rs b/crates/ruff/src/message/junit.rs index 3a8fdd5a4d722..8d4697f3f80ea 100644 --- a/crates/ruff/src/message/junit.rs +++ b/crates/ruff/src/message/junit.rs @@ -45,7 +45,7 @@ impl Emitter for JunitEmitter { } = message; let mut status = TestCaseStatus::non_success(NonSuccessKind::Failure); status.set_message(message.kind.body.clone()); - let location = if context.is_jupyter_notebook(message.filename()) { + let location = if context.is_notebook(message.filename()) { // We can't give a reasonable location for the structured formats, // so we show one that's clearly a fallback SourceLocation::default() diff --git a/crates/ruff/src/message/mod.rs b/crates/ruff/src/message/mod.rs index 33f0eb98a34a2..bcafd6384e485 100644 --- a/crates/ruff/src/message/mod.rs +++ b/crates/ruff/src/message/mod.rs @@ -3,10 +3,8 @@ use std::collections::BTreeMap; use std::io::Write; use std::ops::Deref; -use ruff_text_size::{TextRange, TextSize}; use rustc_hash::FxHashMap; -use crate::source_kind::SourceKind; pub use azure::AzureEmitter; pub use github::GithubEmitter; pub use gitlab::GitlabEmitter; @@ -17,8 +15,11 @@ pub use junit::JunitEmitter; pub use pylint::PylintEmitter; use ruff_diagnostics::{Diagnostic, DiagnosticKind, Fix}; use ruff_source_file::{SourceFile, SourceLocation}; +use ruff_text_size::{TextRange, TextSize}; pub use text::TextEmitter; +use crate::jupyter::Notebook; + mod azure; mod diff; mod github; @@ -129,33 +130,31 @@ pub trait Emitter { /// Context passed to [`Emitter`]. pub struct EmitterContext<'a> { - source_kind: &'a FxHashMap, + notebooks: &'a FxHashMap, } impl<'a> EmitterContext<'a> { - pub fn new(source_kind: &'a FxHashMap) -> Self { - Self { source_kind } + pub fn new(notebooks: &'a FxHashMap) -> Self { + Self { notebooks } } /// Tests if the file with `name` is a jupyter notebook. - pub fn is_jupyter_notebook(&self, name: &str) -> bool { - self.source_kind - .get(name) - .map_or(false, SourceKind::is_jupyter) + pub fn is_notebook(&self, name: &str) -> bool { + self.notebooks.contains_key(name) } - pub fn source_kind(&self, name: &str) -> Option<&SourceKind> { - self.source_kind.get(name) + pub fn notebook(&self, name: &str) -> Option<&Notebook> { + self.notebooks.get(name) } } #[cfg(test)] mod tests { - use ruff_text_size::{TextRange, TextSize}; use rustc_hash::FxHashMap; use ruff_diagnostics::{Diagnostic, DiagnosticKind, Edit, Fix}; use ruff_source_file::SourceFileBuilder; + use ruff_text_size::{TextRange, TextSize}; use crate::message::{Emitter, EmitterContext, Message}; diff --git a/crates/ruff/src/message/pylint.rs b/crates/ruff/src/message/pylint.rs index 1deee6d2f9acb..18f4517650bbc 100644 --- a/crates/ruff/src/message/pylint.rs +++ b/crates/ruff/src/message/pylint.rs @@ -19,7 +19,7 @@ impl Emitter for PylintEmitter { context: &EmitterContext, ) -> anyhow::Result<()> { for message in messages { - let row = if context.is_jupyter_notebook(message.filename()) { + let row = if context.is_notebook(message.filename()) { // We can't give a reasonable location for the structured formats, // so we show one that's clearly a fallback OneIndexed::from_zero_indexed(0) diff --git a/crates/ruff/src/message/text.rs b/crates/ruff/src/message/text.rs index 3aa5ebc5451a8..f0f0df6f169cf 100644 --- a/crates/ruff/src/message/text.rs +++ b/crates/ruff/src/message/text.rs @@ -6,17 +6,16 @@ use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; use bitflags::bitflags; use colored::Colorize; -use ruff_text_size::{TextRange, TextSize}; use ruff_source_file::{OneIndexed, SourceLocation}; +use ruff_text_size::{TextRange, TextSize}; use crate::fs::relativize_path; -use crate::jupyter::{JupyterIndex, Notebook}; +use crate::jupyter::{Notebook, NotebookIndex}; use crate::line_width::{LineWidth, TabSize}; use crate::message::diff::Diff; use crate::message::{Emitter, EmitterContext, Message}; use crate::registry::AsRule; -use crate::source_kind::SourceKind; bitflags! { #[derive(Default)] @@ -72,10 +71,7 @@ impl Emitter for TextEmitter { )?; let start_location = message.compute_start_location(); - let jupyter_index = context - .source_kind(message.filename()) - .and_then(SourceKind::notebook) - .map(Notebook::index); + let jupyter_index = context.notebook(message.filename()).map(Notebook::index); // Check if we're working on a jupyter notebook and translate positions with cell accordingly let diagnostic_location = if let Some(jupyter_index) = jupyter_index { @@ -165,7 +161,7 @@ impl Display for RuleCodeAndBody<'_> { pub(super) struct MessageCodeFrame<'a> { pub(crate) message: &'a Message, - pub(crate) jupyter_index: Option<&'a JupyterIndex>, + pub(crate) jupyter_index: Option<&'a NotebookIndex>, } impl Display for MessageCodeFrame<'_> { @@ -293,12 +289,10 @@ impl Display for MessageCodeFrame<'_> { } fn replace_whitespace(source: &str, annotation_range: TextRange) -> SourceCode { - static TAB_SIZE: TabSize = TabSize(4); // TODO(jonathan): use `tab-size` - let mut result = String::new(); let mut last_end = 0; let mut range = annotation_range; - let mut line_width = LineWidth::new(TAB_SIZE); + let mut line_width = LineWidth::new(TabSize::default()); for (index, c) in source.char_indices() { let old_width = line_width.get(); diff --git a/crates/ruff/src/noqa.rs b/crates/ruff/src/noqa.rs index c2517699b06ac..4711149a9ab9b 100644 --- a/crates/ruff/src/noqa.rs +++ b/crates/ruff/src/noqa.rs @@ -60,7 +60,7 @@ impl<'a> Directive<'a> { if text[..comment_start] .chars() .last() - .map_or(false, |c| c != '#') + .is_some_and(|c| c != '#') { continue; } @@ -562,7 +562,7 @@ fn add_noqa_inner( let mut prev_end = TextSize::default(); for (offset, (rules, directive)) in matches_by_line { - output.push_str(&locator.contents()[TextRange::new(prev_end, offset)]); + output.push_str(locator.slice(TextRange::new(prev_end, offset))); let line = locator.full_line(offset); @@ -619,7 +619,7 @@ fn add_noqa_inner( prev_end = offset + line.text_len(); } - output.push_str(&locator.contents()[usize::from(prev_end)..]); + output.push_str(locator.after(prev_end)); (count, output) } diff --git a/crates/ruff/src/registry/rule_set.rs b/crates/ruff/src/registry/rule_set.rs index 555ba0e5b2f97..e141a4e25e12d 100644 --- a/crates/ruff/src/registry/rule_set.rs +++ b/crates/ruff/src/registry/rule_set.rs @@ -72,7 +72,7 @@ impl RuleSet { /// let set_1 = RuleSet::from_rules(&[Rule::AmbiguousFunctionName, Rule::AnyType]); /// let set_2 = RuleSet::from_rules(&[ /// Rule::BadQuotesInlineString, - /// Rule::BooleanPositionalValueInFunctionCall, + /// Rule::BooleanPositionalValueInCall, /// ]); /// /// let union = set_1.union(&set_2); @@ -80,7 +80,7 @@ impl RuleSet { /// assert!(union.contains(Rule::AmbiguousFunctionName)); /// assert!(union.contains(Rule::AnyType)); /// assert!(union.contains(Rule::BadQuotesInlineString)); - /// assert!(union.contains(Rule::BooleanPositionalValueInFunctionCall)); + /// assert!(union.contains(Rule::BooleanPositionalValueInCall)); /// ``` #[must_use] pub const fn union(mut self, other: &Self) -> Self { @@ -132,7 +132,7 @@ impl RuleSet { /// ]))); /// /// assert!(!set_1.intersects(&RuleSet::from_rules(&[ - /// Rule::BooleanPositionalValueInFunctionCall, + /// Rule::BooleanPositionalValueInCall, /// Rule::BadQuotesInlineString /// ]))); /// ``` diff --git a/crates/ruff/src/renamer.rs b/crates/ruff/src/renamer.rs index 84f4cfbe7666e..2671cd63fe466 100644 --- a/crates/ruff/src/renamer.rs +++ b/crates/ruff/src/renamer.rs @@ -4,6 +4,7 @@ use anyhow::{anyhow, Result}; use itertools::Itertools; use ruff_diagnostics::Edit; +use ruff_python_ast::Ranged; use ruff_python_semantic::{Binding, BindingKind, Scope, ScopeId, SemanticModel}; pub(crate) struct Renamer; @@ -220,21 +221,21 @@ impl Renamer { BindingKind::Import(_) | BindingKind::FromImport(_) => { if binding.is_alias() { // Ex) Rename `import pandas as alias` to `import pandas as pd`. - Some(Edit::range_replacement(target.to_string(), binding.range)) + Some(Edit::range_replacement(target.to_string(), binding.range())) } else { // Ex) Rename `import pandas` to `import pandas as pd`. Some(Edit::range_replacement( format!("{name} as {target}"), - binding.range, + binding.range(), )) } } BindingKind::SubmoduleImport(import) => { // Ex) Rename `import pandas.core` to `import pandas as pd`. - let module_name = import.qualified_name.split('.').next().unwrap(); + let module_name = import.call_path.first().unwrap(); Some(Edit::range_replacement( format!("{module_name} as {target}"), - binding.range, + binding.range(), )) } // Avoid renaming builtins and other "special" bindings. @@ -254,7 +255,7 @@ impl Renamer { | BindingKind::FunctionDefinition(_) | BindingKind::Deletion | BindingKind::UnboundException(_) => { - Some(Edit::range_replacement(target.to_string(), binding.range)) + Some(Edit::range_replacement(target.to_string(), binding.range())) } } } diff --git a/crates/ruff/src/resolver.rs b/crates/ruff/src/resolver.rs index 960c6e1020712..4a84e997ade07 100644 --- a/crates/ruff/src/resolver.rs +++ b/crates/ruff/src/resolver.rs @@ -262,7 +262,6 @@ pub fn python_files_in_path( builder.add(path); } builder.standard_filters(pyproject_config.settings.lib.respect_gitignore); - builder.require_git(false); builder.hidden(false); let walker = builder.build_parallel(); @@ -304,7 +303,7 @@ pub fn python_files_in_path( if let Ok(entry) = &result { if entry .file_type() - .map_or(false, |file_type| file_type.is_dir()) + .is_some_and(|file_type| file_type.is_dir()) { match settings_toml(entry.path()) { Ok(Some(pyproject)) => match resolve_scoped_settings( diff --git a/crates/ruff/src/rules/airflow/rules/task_variable_name.rs b/crates/ruff/src/rules/airflow/rules/task_variable_name.rs index 275f96ad285fd..6a33944448fdf 100644 --- a/crates/ruff/src/rules/airflow/rules/task_variable_name.rs +++ b/crates/ruff/src/rules/airflow/rules/task_variable_name.rs @@ -1,10 +1,8 @@ -use ruff_python_ast as ast; -use ruff_python_ast::{Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast as ast; use ruff_python_ast::Constant; +use ruff_python_ast::{Expr, Ranged}; use crate::checkers::ast::Checker; @@ -60,7 +58,10 @@ pub(crate) fn variable_name_task_id( }; // If the value is not a call, we can't do anything. - let Expr::Call(ast::ExprCall { func, keywords, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, arguments, .. + }) = value + else { return None; }; @@ -68,18 +69,18 @@ pub(crate) fn variable_name_task_id( if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| matches!(call_path[0], "airflow")) + .is_some_and(|call_path| matches!(call_path[0], "airflow")) { return None; } // If the call doesn't have a `task_id` keyword argument, we can't do anything. - let keyword = find_keyword(keywords, "task_id")?; + let keyword = arguments.find_keyword("task_id")?; // If the keyword argument is not a string, we can't do anything. let task_id = match &keyword.value { Expr::Constant(constant) => match &constant.value { - Constant::Str(value) => value, + Constant::Str(ast::StringConstant { value, .. }) => value, _ => return None, }, _ => return None, diff --git a/crates/ruff/src/rules/eradicate/detection.rs b/crates/ruff/src/rules/eradicate/detection.rs index 7cf497536d834..77be87c048f1b 100644 --- a/crates/ruff/src/rules/eradicate/detection.rs +++ b/crates/ruff/src/rules/eradicate/detection.rs @@ -1,8 +1,8 @@ /// See: [eradicate.py](https://github.com/myint/eradicate/blob/98f199940979c94447a461d50d27862b118b282d/eradicate.py) use once_cell::sync::Lazy; use regex::Regex; -use ruff_python_ast::Suite; -use ruff_python_parser::Parse; + +use ruff_python_parser::parse_suite; static ALLOWLIST_REGEX: Lazy = Lazy::new(|| { Regex::new( @@ -28,7 +28,7 @@ static HASH_NUMBER: Lazy = Lazy::new(|| Regex::new(r"#\d").unwrap()); static MULTILINE_ASSIGNMENT_REGEX: Lazy = Lazy::new(|| Regex::new(r"^\s*([(\[]\s*)?(\w+\s*,\s*)*\w+\s*([)\]]\s*)?=.*[(\[{]$").unwrap()); static PARTIAL_DICTIONARY_REGEX: Lazy = - Lazy::new(|| Regex::new(r#"^\s*['"]\w+['"]\s*:.+[,{]\s*$"#).unwrap()); + Lazy::new(|| Regex::new(r#"^\s*['"]\w+['"]\s*:.+[,{]\s*(#.*)?$"#).unwrap()); static PRINT_RETURN_REGEX: Lazy = Lazy::new(|| Regex::new(r"^(print|return)\b\s*").unwrap()); /// Returns `true` if a comment contains Python code. @@ -79,7 +79,7 @@ pub(crate) fn comment_contains_code(line: &str, task_tags: &[String]) -> bool { } // Finally, compile the source code. - Suite::parse(&line, "").is_ok() + parse_suite(&line, "").is_ok() } /// Returns `true` if a line is probably part of some multiline code. diff --git a/crates/ruff/src/rules/eradicate/snapshots/ruff__rules__eradicate__tests__ERA001_ERA001.py.snap b/crates/ruff/src/rules/eradicate/snapshots/ruff__rules__eradicate__tests__ERA001_ERA001.py.snap index 17ccde3ca7e5e..18aa504d2b5bc 100644 --- a/crates/ruff/src/rules/eradicate/snapshots/ruff__rules__eradicate__tests__ERA001_ERA001.py.snap +++ b/crates/ruff/src/rules/eradicate/snapshots/ruff__rules__eradicate__tests__ERA001_ERA001.py.snap @@ -105,5 +105,47 @@ ERA001.py:21:5: ERA001 [*] Found commented-out code 19 19 | class A(): 20 20 | pass 21 |- # b = c +22 21 | +23 22 | +24 23 | dictionary = { + +ERA001.py:26:5: ERA001 [*] Found commented-out code + | +24 | dictionary = { +25 | # "key1": 123, # noqa: ERA001 +26 | # "key2": 456, + | ^^^^^^^^^^^^^^ ERA001 +27 | # "key3": 789, # test +28 | } + | + = help: Remove commented-out code + +ℹ Possible fix +23 23 | +24 24 | dictionary = { +25 25 | # "key1": 123, # noqa: ERA001 +26 |- # "key2": 456, +27 26 | # "key3": 789, # test +28 27 | } +29 28 | + +ERA001.py:27:5: ERA001 [*] Found commented-out code + | +25 | # "key1": 123, # noqa: ERA001 +26 | # "key2": 456, +27 | # "key3": 789, # test + | ^^^^^^^^^^^^^^^^^^^^^^ ERA001 +28 | } + | + = help: Remove commented-out code + +ℹ Possible fix +24 24 | dictionary = { +25 25 | # "key1": 123, # noqa: ERA001 +26 26 | # "key2": 456, +27 |- # "key3": 789, # test +28 27 | } +29 28 | +30 29 | #import os # noqa diff --git a/crates/ruff/src/rules/flake8_2020/helpers.rs b/crates/ruff/src/rules/flake8_2020/helpers.rs index 87df1c4559dd9..4a778c5640bc0 100644 --- a/crates/ruff/src/rules/flake8_2020/helpers.rs +++ b/crates/ruff/src/rules/flake8_2020/helpers.rs @@ -5,5 +5,5 @@ use ruff_python_semantic::SemanticModel; pub(super) fn is_sys(expr: &Expr, target: &str, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(expr) - .map_or(false, |call_path| call_path.as_slice() == ["sys", target]) + .is_some_and(|call_path| call_path.as_slice() == ["sys", target]) } diff --git a/crates/ruff/src/rules/flake8_2020/rules/name_or_attribute.rs b/crates/ruff/src/rules/flake8_2020/rules/name_or_attribute.rs index 3859fd3bc2eb7..a64164d9fe06f 100644 --- a/crates/ruff/src/rules/flake8_2020/rules/name_or_attribute.rs +++ b/crates/ruff/src/rules/flake8_2020/rules/name_or_attribute.rs @@ -49,9 +49,7 @@ pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) { if checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["six", "PY3"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["six", "PY3"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_annotations/fixes.rs b/crates/ruff/src/rules/flake8_annotations/fixes.rs deleted file mode 100644 index 2111978b0458e..0000000000000 --- a/crates/ruff/src/rules/flake8_annotations/fixes.rs +++ /dev/null @@ -1,42 +0,0 @@ -use anyhow::{bail, Result}; -use ruff_python_ast::{Ranged, Stmt}; -use ruff_python_parser::{lexer, Mode, Tok}; - -use ruff_diagnostics::Edit; -use ruff_source_file::Locator; - -/// ANN204 -pub(crate) fn add_return_annotation( - locator: &Locator, - stmt: &Stmt, - annotation: &str, -) -> Result { - let contents = &locator.contents()[stmt.range()]; - - // Find the colon (following the `def` keyword). - let mut seen_lpar = false; - let mut seen_rpar = false; - let mut count = 0u32; - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, stmt.start()).flatten() { - if seen_lpar && seen_rpar { - if matches!(tok, Tok::Colon) { - return Ok(Edit::insertion(format!(" -> {annotation}"), range.start())); - } - } - - if matches!(tok, Tok::Lpar) { - if count == 0 { - seen_lpar = true; - } - count = count.saturating_add(1); - } - if matches!(tok, Tok::Rpar) { - count = count.saturating_sub(1); - if count == 0 { - seen_rpar = true; - } - } - } - - bail!("Unable to locate colon in function definition"); -} diff --git a/crates/ruff/src/rules/flake8_annotations/helpers.rs b/crates/ruff/src/rules/flake8_annotations/helpers.rs index 4d265816a4cd1..42d13735645dc 100644 --- a/crates/ruff/src/rules/flake8_annotations/helpers.rs +++ b/crates/ruff/src/rules/flake8_annotations/helpers.rs @@ -1,53 +1,11 @@ -use ruff_python_ast::{self as ast, Arguments, Expr, Stmt}; - -use ruff_python_ast::cast; use ruff_python_semantic::analyze::visibility; -use ruff_python_semantic::{Definition, Member, MemberKind, SemanticModel}; - -pub(super) fn match_function_def( - stmt: &Stmt, -) -> (&str, &Arguments, Option<&Expr>, &[Stmt], &[ast::Decorator]) { - match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { - name, - args, - returns, - body, - decorator_list, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - name, - args, - returns, - body, - decorator_list, - .. - }) => ( - name, - args, - returns.as_ref().map(AsRef::as_ref), - body, - decorator_list, - ), - _ => panic!("Found non-FunctionDef in match_function_def"), - } -} +use ruff_python_semantic::{Definition, SemanticModel}; /// Return the name of the function, if it's overloaded. pub(crate) fn overloaded_name(definition: &Definition, semantic: &SemanticModel) -> Option { - if let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = definition - { - if visibility::is_overload(cast::decorator_list(stmt), semantic) { - let (name, ..) = match_function_def(stmt); - Some(name.to_string()) - } else { - None - } + let function = definition.as_function_def()?; + if visibility::is_overload(&function.decorator_list, semantic) { + Some(function.name.to_string()) } else { None } @@ -60,19 +18,12 @@ pub(crate) fn is_overload_impl( overloaded_name: &str, semantic: &SemanticModel, ) -> bool { - if let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = definition - { - if visibility::is_overload(cast::decorator_list(stmt), semantic) { - false - } else { - let (name, ..) = match_function_def(stmt); - name == overloaded_name - } - } else { + let Some(function) = definition.as_function_def() else { + return false; + }; + if visibility::is_overload(&function.decorator_list, semantic) { false + } else { + function.name.as_str() == overloaded_name } } diff --git a/crates/ruff/src/rules/flake8_annotations/mod.rs b/crates/ruff/src/rules/flake8_annotations/mod.rs index 9928a48fb1434..2322045c272b0 100644 --- a/crates/ruff/src/rules/flake8_annotations/mod.rs +++ b/crates/ruff/src/rules/flake8_annotations/mod.rs @@ -1,5 +1,4 @@ //! Rules from [flake8-annotations](https://pypi.org/project/flake8-annotations/). -mod fixes; pub(crate) mod helpers; pub(crate) mod rules; pub mod settings; diff --git a/crates/ruff/src/rules/flake8_annotations/rules/definition.rs b/crates/ruff/src/rules/flake8_annotations/rules/definition.rs index 9e7f120f43ac8..fc1678aae22b9 100644 --- a/crates/ruff/src/rules/flake8_annotations/rules/definition.rs +++ b/crates/ruff/src/rules/flake8_annotations/rules/definition.rs @@ -1,23 +1,18 @@ -use ruff_python_ast::{self as ast, ArgWithDefault, Constant, Expr, Ranged, Stmt}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix, Violation}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::cast; use ruff_python_ast::helpers::ReturnStatementVisitor; use ruff_python_ast::identifier::Identifier; use ruff_python_ast::statement_visitor::StatementVisitor; +use ruff_python_ast::{self as ast, Constant, Expr, ParameterWithDefault, Ranged, Stmt}; use ruff_python_parser::typing::parse_type_annotation; use ruff_python_semantic::analyze::visibility; -use ruff_python_semantic::{Definition, Member, MemberKind}; +use ruff_python_semantic::Definition; use ruff_python_stdlib::typing::simple_magic_return_type; use crate::checkers::ast::Checker; use crate::registry::{AsRule, Rule}; use crate::rules::ruff::typing::type_hint_resolves_to_any; -use super::super::fixes; -use super::super::helpers::match_function_def; - /// ## What it does /// Checks that function arguments have type annotations. /// @@ -498,20 +493,23 @@ pub(crate) fn definition( definition: &Definition, visibility: visibility::Visibility, ) -> Vec { - // TODO(charlie): Consider using the AST directly here rather than `Definition`. - // We could adhere more closely to `flake8-annotations` by defining public - // vs. secret vs. protected. - let Definition::Member(Member { kind, stmt, .. }) = definition else { + let Some(function) = definition.as_function_def() else { return vec![]; }; - let is_method = match kind { - MemberKind::Method => true, - MemberKind::Function | MemberKind::NestedFunction => false, - _ => return vec![], - }; + let ast::StmtFunctionDef { + range: _, + is_async: _, + decorator_list, + name, + type_params: _, + parameters, + returns, + body, + } = function; + + let is_method = definition.is_method(); - let (name, arguments, returns, body, decorator_list) = match_function_def(stmt); // Keep track of whether we've seen any typed arguments or return values. let mut has_any_typed_arg = false; // Any argument has been typed? let mut has_typed_return = false; // Return value has been typed? @@ -524,44 +522,46 @@ pub(crate) fn definition( let is_overridden = visibility::is_override(decorator_list, checker.semantic()); // ANN001, ANN401 - for ArgWithDefault { - def, + for ParameterWithDefault { + parameter, default: _, range: _, - } in arguments + } in parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) .skip( // If this is a non-static method, skip `cls` or `self`. usize::from( - is_method - && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()), + is_method && !visibility::is_staticmethod(decorator_list, checker.semantic()), ), ) { - // ANN401 for dynamically typed arguments - if let Some(annotation) = &def.annotation { + // ANN401 for dynamically typed parameters + if let Some(annotation) = ¶meter.annotation { has_any_typed_arg = true; if checker.enabled(Rule::AnyType) && !is_overridden { check_dynamically_typed( checker, annotation, - || def.arg.to_string(), + || parameter.name.to_string(), &mut diagnostics, ); } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&def.arg)) + && checker + .settings + .dummy_variable_rgx + .is_match(¶meter.name)) { if checker.enabled(Rule::MissingTypeFunctionArgument) { diagnostics.push(Diagnostic::new( MissingTypeFunctionArgument { - name: def.arg.to_string(), + name: parameter.name.to_string(), }, - def.range(), + parameter.range(), )); } } @@ -569,23 +569,23 @@ pub(crate) fn definition( } // ANN002, ANN401 - if let Some(arg) = &arguments.vararg { + if let Some(arg) = ¶meters.vararg { if let Some(expr) = &arg.annotation { has_any_typed_arg = true; if !checker.settings.flake8_annotations.allow_star_arg_any { if checker.enabled(Rule::AnyType) && !is_overridden { - let name = &arg.arg; + let name = &arg.name; check_dynamically_typed(checker, expr, || format!("*{name}"), &mut diagnostics); } } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&arg.arg)) + && checker.settings.dummy_variable_rgx.is_match(&arg.name)) { if checker.enabled(Rule::MissingTypeArgs) { diagnostics.push(Diagnostic::new( MissingTypeArgs { - name: arg.arg.to_string(), + name: arg.name.to_string(), }, arg.range(), )); @@ -595,12 +595,12 @@ pub(crate) fn definition( } // ANN003, ANN401 - if let Some(arg) = &arguments.kwarg { + if let Some(arg) = ¶meters.kwarg { if let Some(expr) = &arg.annotation { has_any_typed_arg = true; if !checker.settings.flake8_annotations.allow_star_arg_any { if checker.enabled(Rule::AnyType) && !is_overridden { - let name = &arg.arg; + let name = &arg.name; check_dynamically_typed( checker, expr, @@ -611,12 +611,12 @@ pub(crate) fn definition( } } else { if !(checker.settings.flake8_annotations.suppress_dummy_args - && checker.settings.dummy_variable_rgx.is_match(&arg.arg)) + && checker.settings.dummy_variable_rgx.is_match(&arg.name)) { if checker.enabled(Rule::MissingTypeKwargs) { diagnostics.push(Diagnostic::new( MissingTypeKwargs { - name: arg.arg.to_string(), + name: arg.name.to_string(), }, arg.range(), )); @@ -626,33 +626,33 @@ pub(crate) fn definition( } // ANN101, ANN102 - if is_method && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) { - if let Some(ArgWithDefault { - def, + if is_method && !visibility::is_staticmethod(decorator_list, checker.semantic()) { + if let Some(ParameterWithDefault { + parameter, default: _, range: _, - }) = arguments + }) = parameters .posonlyargs .first() - .or_else(|| arguments.args.first()) + .or_else(|| parameters.args.first()) { - if def.annotation.is_none() { - if visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) { + if parameter.annotation.is_none() { + if visibility::is_classmethod(decorator_list, checker.semantic()) { if checker.enabled(Rule::MissingTypeCls) { diagnostics.push(Diagnostic::new( MissingTypeCls { - name: def.arg.to_string(), + name: parameter.name.to_string(), }, - def.range(), + parameter.range(), )); } } else { if checker.enabled(Rule::MissingTypeSelf) { diagnostics.push(Diagnostic::new( MissingTypeSelf { - name: def.arg.to_string(), + name: parameter.name.to_string(), }, - def.range(), + parameter.range(), )); } } @@ -673,24 +673,22 @@ pub(crate) fn definition( // (explicitly or implicitly). checker.settings.flake8_annotations.suppress_none_returning && is_none_returning(body) ) { - if is_method && visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) { + if is_method && visibility::is_classmethod(decorator_list, checker.semantic()) { if checker.enabled(Rule::MissingReturnTypeClassMethod) { diagnostics.push(Diagnostic::new( MissingReturnTypeClassMethod { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), )); } - } else if is_method - && visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) - { + } else if is_method && visibility::is_staticmethod(decorator_list, checker.semantic()) { if checker.enabled(Rule::MissingReturnTypeStaticMethod) { diagnostics.push(Diagnostic::new( MissingReturnTypeStaticMethod { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), )); } } else if is_method && visibility::is_init(name) { @@ -702,13 +700,13 @@ pub(crate) fn definition( MissingReturnTypeSpecialMethod { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), ); if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::add_return_annotation(checker.locator(), stmt, "None") - .map(Fix::suggested) - }); + diagnostic.set_fix(Fix::suggested(Edit::insertion( + " -> None".to_string(), + function.parameters.range().end(), + ))); } diagnostics.push(diagnostic); } @@ -719,14 +717,14 @@ pub(crate) fn definition( MissingReturnTypeSpecialMethod { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), ); if checker.patch(diagnostic.kind.rule()) { if let Some(return_type) = simple_magic_return_type(name) { - diagnostic.try_set_fix(|| { - fixes::add_return_annotation(checker.locator(), stmt, return_type) - .map(Fix::suggested) - }); + diagnostic.set_fix(Fix::suggested(Edit::insertion( + format!(" -> {return_type}"), + function.parameters.range().end(), + ))); } } diagnostics.push(diagnostic); @@ -739,7 +737,7 @@ pub(crate) fn definition( MissingReturnTypeUndocumentedPublicFunction { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), )); } } @@ -749,7 +747,7 @@ pub(crate) fn definition( MissingReturnTypePrivateFunction { name: name.to_string(), }, - stmt.identifier(), + function.identifier(), )); } } diff --git a/crates/ruff/src/rules/flake8_annotations/snapshots/ruff__rules__flake8_annotations__tests__defaults.snap b/crates/ruff/src/rules/flake8_annotations/snapshots/ruff__rules__flake8_annotations__tests__defaults.snap index 54e30dd686e64..03944c6d78df5 100644 --- a/crates/ruff/src/rules/flake8_annotations/snapshots/ruff__rules__flake8_annotations__tests__defaults.snap +++ b/crates/ruff/src/rules/flake8_annotations/snapshots/ruff__rules__flake8_annotations__tests__defaults.snap @@ -242,4 +242,22 @@ annotation_presence.py:154:10: ANN401 Dynamically typed expressions (typing.Any) | ^^^^^^^^^^^^^^^^^^^^^^^^ ANN401 | +annotation_presence.py:159:9: ANN204 [*] Missing return type annotation for special method `__init__` + | +157 | class Foo: +158 | @decorator() +159 | def __init__(self: "Foo", foo: int): + | ^^^^^^^^ ANN204 +160 | ... + | + = help: Add `None` return type + +ℹ Suggested fix +156 156 | +157 157 | class Foo: +158 158 | @decorator() +159 |- def __init__(self: "Foo", foo: int): + 159 |+ def __init__(self: "Foo", foo: int) -> None: +160 160 | ... + diff --git a/crates/ruff/src/rules/flake8_async/rules/blocking_http_call.rs b/crates/ruff/src/rules/flake8_async/rules/blocking_http_call.rs index a06ce6dca36db..41541d51006f6 100644 --- a/crates/ruff/src/rules/flake8_async/rules/blocking_http_call.rs +++ b/crates/ruff/src/rules/flake8_async/rules/blocking_http_call.rs @@ -68,7 +68,7 @@ pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) { .semantic() .resolve_call_path(func) .as_ref() - .map_or(false, is_blocking_http_call) + .is_some_and(is_blocking_http_call) { checker.diagnostics.push(Diagnostic::new( BlockingHttpCallInAsyncFunction, diff --git a/crates/ruff/src/rules/flake8_async/rules/blocking_os_call.rs b/crates/ruff/src/rules/flake8_async/rules/blocking_os_call.rs index 4757839bb92d7..212736b4d611b 100644 --- a/crates/ruff/src/rules/flake8_async/rules/blocking_os_call.rs +++ b/crates/ruff/src/rules/flake8_async/rules/blocking_os_call.rs @@ -48,7 +48,7 @@ pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) { .semantic() .resolve_call_path(func) .as_ref() - .map_or(false, is_unsafe_os_method) + .is_some_and(is_unsafe_os_method) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_async/rules/open_sleep_or_subprocess_call.rs b/crates/ruff/src/rules/flake8_async/rules/open_sleep_or_subprocess_call.rs index 7de7c4b0ef474..220b8f31626d1 100644 --- a/crates/ruff/src/rules/flake8_async/rules/open_sleep_or_subprocess_call.rs +++ b/crates/ruff/src/rules/flake8_async/rules/open_sleep_or_subprocess_call.rs @@ -48,7 +48,7 @@ pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) .semantic() .resolve_call_path(func) .as_ref() - .map_or(false, is_open_sleep_or_subprocess_call) + .is_some_and(is_open_sleep_or_subprocess_call) { checker.diagnostics.push(Diagnostic::new( OpenSleepOrSubprocessInAsyncFunction, diff --git a/crates/ruff/src/rules/flake8_bandit/helpers.rs b/crates/ruff/src/rules/flake8_bandit/helpers.rs index 0837d4747e504..0c019360fe5db 100644 --- a/crates/ruff/src/rules/flake8_bandit/helpers.rs +++ b/crates/ruff/src/rules/flake8_bandit/helpers.rs @@ -26,18 +26,14 @@ pub(super) fn is_untyped_exception(type_: Option<&Expr>, semantic: &SemanticMode type_.map_or(true, |type_| { if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ { elts.iter().any(|type_| { - semantic - .resolve_call_path(type_) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "Exception" | "BaseException"]) - }) - }) - } else { - semantic - .resolve_call_path(type_) - .map_or(false, |call_path| { + semantic.resolve_call_path(type_).is_some_and(|call_path| { matches!(call_path.as_slice(), ["", "Exception" | "BaseException"]) }) + }) + } else { + semantic.resolve_call_path(type_).is_some_and(|call_path| { + matches!(call_path.as_slice(), ["", "Exception" | "BaseException"]) + }) } }) } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs index 1a42c17f313c2..1da82b46816e8 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs @@ -1,10 +1,9 @@ use num_traits::ToPrimitive; -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Operator, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::CallPath; -use ruff_python_ast::helpers::CallArguments; +use ruff_python_ast::{self as ast, Constant, Expr, Operator, Ranged}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -48,21 +47,13 @@ impl Violation for BadFilePermissions { } /// S103 -pub(crate) fn bad_file_permissions( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn bad_file_permissions(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["os", "chmod"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["os", "chmod"])) { - let call_args = CallArguments::new(args, keywords); - if let Some(mode_arg) = call_args.argument("mode", 1) { + if let Some(mode_arg) = call.arguments.find_argument("mode", 1) { if let Some(int_value) = int_value(mode_arg, checker.semantic()) { if (int_value & WRITE_WORLD > 0) || (int_value & EXECUTE_GROUP > 0) { checker.diagnostics.push(Diagnostic::new( @@ -121,21 +112,21 @@ fn py_stat(call_path: &CallPath) -> Option { } } -fn int_value(expr: &Expr, model: &SemanticModel) -> Option { +fn int_value(expr: &Expr, semantic: &SemanticModel) -> Option { match expr { Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. }) => value.to_u16(), - Expr::Attribute(_) => model.resolve_call_path(expr).as_ref().and_then(py_stat), + Expr::Attribute(_) => semantic.resolve_call_path(expr).as_ref().and_then(py_stat), Expr::BinOp(ast::ExprBinOp { left, op, right, range: _, }) => { - let left_value = int_value(left, model)?; - let right_value = int_value(right, model)?; + let left_value = int_value(left, semantic)?; + let right_value = int_value(right, semantic)?; match op { Operator::BitAnd => Some(left_value & right_value), Operator::BitOr => Some(left_value | right_value), diff --git a/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs b/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs index 14de0c36d4fd2..f41ac62cdbf3e 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/exec_used.rs @@ -35,9 +35,7 @@ pub(crate) fn exec_used(checker: &mut Checker, func: &Expr) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["" | "builtin", "exec"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["" | "builtin", "exec"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs index 82b2bff33caec..a0bcc73899401 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_password_default.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arg, ArgWithDefault, Arguments, Expr, Ranged}; +use ruff_python_ast::{Expr, Parameter, ParameterWithDefault, Parameters, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -53,9 +53,9 @@ impl Violation for HardcodedPasswordDefault { } } -fn check_password_kwarg(arg: &Arg, default: &Expr) -> Option { +fn check_password_kwarg(parameter: &Parameter, default: &Expr) -> Option { string_literal(default).filter(|string| !string.is_empty())?; - let kwarg_name = &arg.arg; + let kwarg_name = ¶meter.name; if !matches_password_name(kwarg_name) { return None; } @@ -68,21 +68,21 @@ fn check_password_kwarg(arg: &Arg, default: &Expr) -> Option { } /// S107 -pub(crate) fn hardcoded_password_default(checker: &mut Checker, arguments: &Arguments) { - for ArgWithDefault { - def, +pub(crate) fn hardcoded_password_default(checker: &mut Checker, parameters: &Parameters) { + for ParameterWithDefault { + parameter, default, range: _, - } in arguments + } in parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) { let Some(default) = default else { continue; }; - if let Some(diagnostic) = check_password_kwarg(def, default) { + if let Some(diagnostic) = check_password_kwarg(parameter, default) { checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs index 5b63205d5f8f5..9d82380f4e447 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs @@ -53,7 +53,7 @@ fn matches_sql_statement(string: &str) -> bool { SQL_REGEX.is_match(string) } -fn matches_string_format_expression(expr: &Expr, model: &SemanticModel) -> bool { +fn matches_string_format_expression(expr: &Expr, semantic: &SemanticModel) -> bool { match expr { // "select * from table where val = " + "str" + ... // "select * from table where val = %s" % ... @@ -62,8 +62,8 @@ fn matches_string_format_expression(expr: &Expr, model: &SemanticModel) -> bool .. }) => { // Only evaluate the full BinOp, not the nested components. - if model - .expr_parent() + if semantic + .current_expression_parent() .map_or(true, |parent| !parent.is_bin_op_expr()) { if any_over_expr(expr, &has_string_literal) { @@ -80,7 +80,7 @@ fn matches_string_format_expression(expr: &Expr, model: &SemanticModel) -> bool attr == "format" && string_literal(value).is_some() } // f"select * from table where val = {val}" - Expr::JoinedStr(_) => true, + Expr::FString(_) => true, _ => false, } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs index 7993dd1b24a1a..c677e9e909f2c 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs @@ -1,8 +1,10 @@ -use ruff_python_ast::{Expr, Ranged}; +use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use crate::checkers::ast::Checker; + /// ## What it does /// Checks for the use of hardcoded temporary file or directory paths. /// @@ -49,19 +51,33 @@ impl Violation for HardcodedTempFile { } /// S108 -pub(crate) fn hardcoded_tmp_directory( - expr: &Expr, - value: &str, - prefixes: &[String], -) -> Option { - if prefixes.iter().any(|prefix| value.starts_with(prefix)) { - Some(Diagnostic::new( - HardcodedTempFile { - string: value.to_string(), - }, - expr.range(), - )) - } else { - None +pub(crate) fn hardcoded_tmp_directory(checker: &mut Checker, expr: &Expr, value: &str) { + if !checker + .settings + .flake8_bandit + .hardcoded_tmp_directory + .iter() + .any(|prefix| value.starts_with(prefix)) + { + return; + } + + if let Some(Expr::Call(ast::ExprCall { func, .. })) = + checker.semantic().current_expression_parent() + { + if checker + .semantic() + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["tempfile", ..])) + { + return; + } } + + checker.diagnostics.push(Diagnostic::new( + HardcodedTempFile { + string: value.to_string(), + }, + expr.range(), + )); } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs index 75c15bbbd99a6..df5b8534f8b09 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_false, CallArguments}; +use ruff_python_ast::helpers::is_const_false; +use ruff_python_ast::{self as ast, Arguments, Ranged}; use crate::checkers::ast::Checker; @@ -60,30 +59,26 @@ impl Violation for HashlibInsecureHashFunction { } /// S324 -pub(crate) fn hashlib_insecure_hash_functions( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { - if let Some(hashlib_call) = checker - .semantic() - .resolve_call_path(func) - .and_then(|call_path| match call_path.as_slice() { - ["hashlib", "new"] => Some(HashlibCall::New), - ["hashlib", "md4"] => Some(HashlibCall::WeakHash("md4")), - ["hashlib", "md5"] => Some(HashlibCall::WeakHash("md5")), - ["hashlib", "sha"] => Some(HashlibCall::WeakHash("sha")), - ["hashlib", "sha1"] => Some(HashlibCall::WeakHash("sha1")), - _ => None, - }) +pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast::ExprCall) { + if let Some(hashlib_call) = + checker + .semantic() + .resolve_call_path(&call.func) + .and_then(|call_path| match call_path.as_slice() { + ["hashlib", "new"] => Some(HashlibCall::New), + ["hashlib", "md4"] => Some(HashlibCall::WeakHash("md4")), + ["hashlib", "md5"] => Some(HashlibCall::WeakHash("md5")), + ["hashlib", "sha"] => Some(HashlibCall::WeakHash("sha")), + ["hashlib", "sha1"] => Some(HashlibCall::WeakHash("sha1")), + _ => None, + }) { - if !is_used_for_security(keywords) { + if !is_used_for_security(&call.arguments) { return; } match hashlib_call { HashlibCall::New => { - if let Some(name_arg) = CallArguments::new(args, keywords).argument("name", 0) { + if let Some(name_arg) = call.arguments.find_argument("name", 0) { if let Some(hash_func_name) = string_literal(name_arg) { // `hashlib.new` accepts both lowercase and uppercase names for hash // functions. @@ -106,15 +101,16 @@ pub(crate) fn hashlib_insecure_hash_functions( HashlibInsecureHashFunction { string: (*func_name).to_string(), }, - func.range(), + call.func.range(), )); } } } } -fn is_used_for_security(keywords: &[Keyword]) -> bool { - find_keyword(keywords, "usedforsecurity") +fn is_used_for_security(arguments: &Arguments) -> bool { + arguments + .find_keyword("usedforsecurity") .map_or(true, |keyword| !is_const_false(&keyword.value)) } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs index 996c8cf4f5c01..799a1268df113 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::helpers::find_keyword; -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; @@ -59,15 +57,13 @@ impl Violation for Jinja2AutoescapeFalse { } /// S701 -pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["jinja2", "Environment"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["jinja2", "Environment"])) { - if let Some(keyword) = find_keyword(keywords, "autoescape") { + if let Some(keyword) = call.arguments.find_keyword("autoescape") { match &keyword.value { Expr::Constant(ast::ExprConstant { value: Constant::Bool(true), @@ -91,7 +87,7 @@ pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, func: &Expr, keywor } else { checker.diagnostics.push(Diagnostic::new( Jinja2AutoescapeFalse { value: false }, - func.range(), + call.func.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs index 46ff796bd39a6..5c936a87d615c 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -35,24 +33,19 @@ impl Violation for LoggingConfigInsecureListen { } /// S612 -pub(crate) fn logging_config_insecure_listen( - checker: &mut Checker, - func: &Expr, - keywords: &[Keyword], -) { +pub(crate) fn logging_config_insecure_listen(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["logging", "config", "listen"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["logging", "config", "listen"])) { - if find_keyword(keywords, "verify").is_some() { + if call.arguments.find_keyword("verify").is_some() { return; } - checker - .diagnostics - .push(Diagnostic::new(LoggingConfigInsecureListen, func.range())); + checker.diagnostics.push(Diagnostic::new( + LoggingConfigInsecureListen, + call.func.range(), + )); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs b/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs index 87644176e8deb..adf916e97c8c1 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs @@ -39,9 +39,7 @@ pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["paramiko", "exec_command"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["paramiko", "exec_command"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs index d2f7d511ce301..843d31733547f 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_false}; +use ruff_python_ast::helpers::is_const_false; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -46,14 +45,10 @@ impl Violation for RequestWithNoCertValidation { } /// S501 -pub(crate) fn request_with_no_cert_validation( - checker: &mut Checker, - func: &Expr, - keywords: &[Keyword], -) { +pub(crate) fn request_with_no_cert_validation(checker: &mut Checker, call: &ast::ExprCall) { if let Some(target) = checker .semantic() - .resolve_call_path(func) + .resolve_call_path(&call.func) .and_then(|call_path| match call_path.as_slice() { ["requests", "get" | "options" | "head" | "post" | "put" | "patch" | "delete"] => { Some("requests") @@ -63,7 +58,7 @@ pub(crate) fn request_with_no_cert_validation( _ => None, }) { - if let Some(keyword) = find_keyword(keywords, "verify") { + if let Some(keyword) = call.arguments.find_keyword("verify") { if is_const_false(&keyword.value) { checker.diagnostics.push(Diagnostic::new( RequestWithNoCertValidation { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs index 5711403505e00..37bf931fabd22 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -49,11 +48,11 @@ impl Violation for RequestWithoutTimeout { } /// S113 -pub(crate) fn request_without_timeout(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn request_without_timeout(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { + .resolve_call_path(&call.func) + .is_some_and(|call_path| { matches!( call_path.as_slice(), [ @@ -63,7 +62,7 @@ pub(crate) fn request_without_timeout(checker: &mut Checker, func: &Expr, keywor ) }) { - if let Some(keyword) = find_keyword(keywords, "timeout") { + if let Some(keyword) = call.arguments.find_keyword("timeout") { if is_const_none(&keyword.value) { checker.diagnostics.push(Diagnostic::new( RequestWithoutTimeout { implicit: false }, @@ -73,7 +72,7 @@ pub(crate) fn request_without_timeout(checker: &mut Checker, func: &Expr, keywor } else { checker.diagnostics.push(Diagnostic::new( RequestWithoutTimeout { implicit: true }, - func.range(), + call.func.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs index fbfd7d4f68b4b..93e6c0c27ea6a 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs @@ -1,16 +1,40 @@ //! Checks relating to shell injection. -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, Truthiness}; +use ruff_python_ast::helpers::Truthiness; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Keyword, Ranged}; use ruff_python_semantic::SemanticModel; use crate::{ checkers::ast::Checker, registry::Rule, rules::flake8_bandit::helpers::string_literal, }; +/// ## What it does +/// Check for method calls that initiate a subprocess with a shell. +/// +/// ## Why is this bad? +/// Starting a subprocess with a shell can allow attackers to execute arbitrary +/// shell commands. Consider starting the process without a shell call and +/// sanitize the input to mitigate the risk of shell injection. +/// +/// ## Example +/// ```python +/// import subprocess +/// +/// subprocess.run("ls -l", shell=True) +/// ``` +/// +/// Use instead: +/// ```python +/// import subprocess +/// +/// subprocess.run(["ls", "-l"]) +/// ``` +/// +/// ## References +/// - [Python documentation: `subprocess` — Subprocess management](https://docs.python.org/3/library/subprocess.html) +/// - [Common Weakness Enumeration: CWE-78](https://cwe.mitre.org/data/definitions/78.html) #[violation] pub struct SubprocessPopenWithShellEqualsTrue { seems_safe: bool, @@ -29,6 +53,30 @@ impl Violation for SubprocessPopenWithShellEqualsTrue { } } +/// ## What it does +/// Check for method calls that initiate a subprocess without a shell. +/// +/// ## Why is this bad? +/// Starting a subprocess without a shell can prevent attackers from executing +/// arbitrary shell commands; however, it is still error-prone. Consider +/// validating the input. +/// +/// ## Known problems +/// Prone to false positives as it is difficult to determine whether the +/// passed arguments have been validated ([#4045]). +/// +/// ## Example +/// ```python +/// import subprocess +/// +/// cmd = input("Enter a command: ").split() +/// subprocess.run(cmd) +/// ``` +/// +/// ## References +/// - [Python documentation: `subprocess` — Subprocess management](https://docs.python.org/3/library/subprocess.html) +/// +/// [#4045]: https://github.com/astral-sh/ruff/issues/4045 #[violation] pub struct SubprocessWithoutShellEqualsTrue; @@ -144,17 +192,12 @@ impl Violation for UnixCommandWildcardInjection { } /// S602, S603, S604, S605, S606, S607, S609 -pub(crate) fn shell_injection( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { - let call_kind = get_call_kind(func, checker.semantic()); - let shell_keyword = find_shell_keyword(keywords, checker.semantic()); +pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) { + let call_kind = get_call_kind(&call.func, checker.semantic()); + let shell_keyword = find_shell_keyword(&call.arguments, checker.semantic()); if matches!(call_kind, Some(CallKind::Subprocess)) { - if let Some(arg) = args.first() { + if let Some(arg) = call.arguments.args.first() { match shell_keyword { // S602 Some(ShellKeyword { @@ -209,7 +252,7 @@ pub(crate) fn shell_injection( // S605 if checker.enabled(Rule::StartProcessWithAShell) { if matches!(call_kind, Some(CallKind::Shell)) { - if let Some(arg) = args.first() { + if let Some(arg) = call.arguments.args.first() { checker.diagnostics.push(Diagnostic::new( StartProcessWithAShell { seems_safe: shell_call_seems_safe(arg), @@ -225,14 +268,14 @@ pub(crate) fn shell_injection( if matches!(call_kind, Some(CallKind::NoShell)) { checker .diagnostics - .push(Diagnostic::new(StartProcessWithNoShell, func.range())); + .push(Diagnostic::new(StartProcessWithNoShell, call.func.range())); } } // S607 if checker.enabled(Rule::StartProcessWithPartialPath) { if call_kind.is_some() { - if let Some(arg) = args.first() { + if let Some(arg) = call.arguments.args.first() { if is_partial_path(arg) { checker .diagnostics @@ -256,11 +299,12 @@ pub(crate) fn shell_injection( ) ) { - if let Some(arg) = args.first() { + if let Some(arg) = call.arguments.args.first() { if is_wildcard_command(arg) { - checker - .diagnostics - .push(Diagnostic::new(UnixCommandWildcardInjection, func.range())); + checker.diagnostics.push(Diagnostic::new( + UnixCommandWildcardInjection, + call.func.range(), + )); } } } @@ -317,10 +361,10 @@ struct ShellKeyword<'a> { /// Return the `shell` keyword argument to the given function call, if any. fn find_shell_keyword<'a>( - keywords: &'a [Keyword], + arguments: &'a Arguments, semantic: &SemanticModel, ) -> Option> { - find_keyword(keywords, "shell").map(|keyword| ShellKeyword { + arguments.find_keyword("shell").map(|keyword| ShellKeyword { truthiness: Truthiness::from_expr(&keyword.value, |id| semantic.is_builtin(id)), keyword, }) @@ -379,7 +423,7 @@ fn is_partial_path(expr: &Expr) -> bool { Expr::List(ast::ExprList { elts, .. }) => elts.first().and_then(string_literal), _ => string_literal(expr), }; - string_literal.map_or(false, |text| !is_full_path(text)) + string_literal.is_some_and(|text| !is_full_path(text)) } /// Return `true` if the [`Expr`] is a wildcard command. @@ -410,7 +454,7 @@ fn is_wildcard_command(expr: &Expr) -> bool { has_star && has_command } else { let string_literal = string_literal(expr); - string_literal.map_or(false, |text| { + string_literal.is_some_and(|text| { text.contains('*') && (text.contains("chown") || text.contains("chmod") diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs index 4e9f276f66215..845dc3affc2f1 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs @@ -1,9 +1,8 @@ use num_traits::{One, Zero}; -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; @@ -43,15 +42,15 @@ impl Violation for SnmpInsecureVersion { } /// S508 -pub(crate) fn snmp_insecure_version(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn snmp_insecure_version(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { + .resolve_call_path(&call.func) + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["pysnmp", "hlapi", "CommunityData"]) }) { - if let Some(keyword) = find_keyword(keywords, "mpModel") { + if let Some(keyword) = call.arguments.find_keyword("mpModel") { if let Expr::Constant(ast::ExprConstant { value: Constant::Int(value), .. diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs index 78274ff0f4851..3dd991664d76f 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::CallArguments; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -42,23 +40,18 @@ impl Violation for SnmpWeakCryptography { } /// S509 -pub(crate) fn snmp_weak_cryptography( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { - if checker - .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pysnmp", "hlapi", "UsmUserData"]) - }) - { - if CallArguments::new(args, keywords).len() < 3 { +pub(crate) fn snmp_weak_cryptography(checker: &mut Checker, call: &ast::ExprCall) { + if call.arguments.len() < 3 { + if checker + .semantic() + .resolve_call_path(&call.func) + .is_some_and(|call_path| { + matches!(call_path.as_slice(), ["pysnmp", "hlapi", "UsmUserData"]) + }) + { checker .diagnostics - .push(Diagnostic::new(SnmpWeakCryptography, func.range())); + .push(Diagnostic::new(SnmpWeakCryptography, call.func.range())); } } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs index 05bfc7aec9cc1..7e706dae54327 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs @@ -76,7 +76,7 @@ impl Violation for SuspiciousPickleUsage { /// import marshal /// /// with open("foo.marshal", "rb") as file: -/// foo = pickle.load(file) +/// foo = marshal.load(file) /// ``` /// /// Use instead: diff --git a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs index cbe45c8c650f4..3ae1a7689f012 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::CallArguments; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; @@ -60,25 +58,17 @@ impl Violation for UnsafeYAMLLoad { } /// S506 -pub(crate) fn unsafe_yaml_load( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn unsafe_yaml_load(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["yaml", "load"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["yaml", "load"])) { - let call_args = CallArguments::new(args, keywords); - if let Some(loader_arg) = call_args.argument("Loader", 1) { + if let Some(loader_arg) = call.arguments.find_argument("Loader", 1) { if !checker .semantic() .resolve_call_path(loader_arg) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["yaml", "SafeLoader" | "CSafeLoader"]) }) { @@ -95,7 +85,7 @@ pub(crate) fn unsafe_yaml_load( } else { checker.diagnostics.push(Diagnostic::new( UnsafeYAMLLoad { loader: None }, - func.range(), + call.func.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_blind_except/rules/blind_except.rs b/crates/ruff/src/rules/flake8_blind_except/rules/blind_except.rs index ac8b34c59fd0d..4fa9474d01af0 100644 --- a/crates/ruff/src/rules/flake8_blind_except/rules/blind_except.rs +++ b/crates/ruff/src/rules/flake8_blind_except/rules/blind_except.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_true}; +use ruff_python_ast::helpers::is_const_true; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use ruff_python_semantic::analyze::logging; use crate::checkers::ast::Checker; @@ -77,7 +76,7 @@ pub(crate) fn blind_except( if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt { if let Some(exc) = exc { if let Expr::Name(ast::ExprName { id, .. }) = exc.as_ref() { - name.map_or(false, |name| id == name) + name.is_some_and(|name| id == name) } else { false } @@ -94,7 +93,10 @@ pub(crate) fn blind_except( // If the exception is logged, don't flag an error. if body.iter().any(|stmt| { if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { - if let Expr::Call(ast::ExprCall { func, keywords, .. }) = value.as_ref() { + if let Expr::Call(ast::ExprCall { + func, arguments, .. + }) = value.as_ref() + { if logging::is_logger_candidate( func, checker.semantic(), @@ -106,7 +108,7 @@ pub(crate) fn blind_except( return true; } if attr == "error" { - if let Some(keyword) = find_keyword(keywords, "exc_info") { + if let Some(keyword) = arguments.find_keyword("exc_info") { if is_const_true(&keyword.value) { return true; } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs b/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs index 8b4f414a51936..8ff583d7fbd78 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs @@ -1,14 +1,11 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; - -use ruff_diagnostics::{Diagnostic, DiagnosticKind}; - -use crate::checkers::ast::Checker; +use ruff_python_ast::{self as ast, Constant, Expr}; /// Returns `true` if a function call is allowed to use a boolean trap. pub(super) fn is_allowed_func_call(name: &str) -> bool { matches!( name, - "append" + "__setattr__" + | "append" | "assertEqual" | "assertEquals" | "assertNotEqual" @@ -28,13 +25,15 @@ pub(super) fn is_allowed_func_call(name: &str) -> bool { | "index" | "insert" | "int" + | "is_" + | "is_not" + | "next" | "param" | "pop" | "remove" | "set_blocking" | "set_enabled" | "setattr" - | "__setattr__" | "setdefault" | "str" ) @@ -60,18 +59,13 @@ pub(super) fn allow_boolean_trap(func: &Expr) -> bool { false } -const fn is_boolean_arg(arg: &Expr) -> bool { +/// Returns `true` if an expression is a boolean literal. +pub(super) const fn is_boolean(expr: &Expr) -> bool { matches!( - &arg, + &expr, Expr::Constant(ast::ExprConstant { value: Constant::Bool(_), .. }) ) } - -pub(super) fn add_if_boolean(checker: &mut Checker, arg: &Expr, kind: DiagnosticKind) { - if is_boolean_arg(arg) { - checker.diagnostics.push(Diagnostic::new(kind, arg.range())); - } -} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/mod.rs b/crates/ruff/src/rules/flake8_boolean_trap/mod.rs index ab0d6f87418fb..7a4a1ff943bb3 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/mod.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/mod.rs @@ -13,9 +13,9 @@ mod tests { use crate::test::test_path; use crate::{assert_messages, settings}; - #[test_case(Rule::BooleanPositionalArgInFunctionDefinition, Path::new("FBT.py"))] - #[test_case(Rule::BooleanDefaultValueInFunctionDefinition, Path::new("FBT.py"))] - #[test_case(Rule::BooleanPositionalValueInFunctionCall, Path::new("FBT.py"))] + #[test_case(Rule::BooleanTypeHintPositionalArgument, Path::new("FBT.py"))] + #[test_case(Rule::BooleanDefaultValuePositionalArgument, Path::new("FBT.py"))] + #[test_case(Rule::BooleanPositionalValueInCall, Path::new("FBT.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs new file mode 100644 index 0000000000000..b80bff7752d3b --- /dev/null +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs @@ -0,0 +1,126 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::call_path::collect_call_path; +use ruff_python_ast::{Decorator, ParameterWithDefault, Parameters, Ranged}; + +use crate::checkers::ast::Checker; +use crate::rules::flake8_boolean_trap::helpers::{is_allowed_func_def, is_boolean}; + +/// ## What it does +/// Checks for the use of boolean positional arguments in function definitions, +/// as determined by the presence of a boolean default value. +/// +/// ## Why is this bad? +/// Calling a function with boolean positional arguments is confusing as the +/// meaning of the boolean value is not clear to the caller and to future +/// readers of the code. +/// +/// The use of a boolean will also limit the function to only two possible +/// behaviors, which makes the function difficult to extend in the future. +/// +/// Instead, consider refactoring into separate implementations for the +/// `True` and `False` cases, using an `Enum`, or making the argument a +/// keyword-only argument, to force callers to be explicit when providing +/// the argument. +/// +/// ## Example +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number, up=True): +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, True) # What does `True` mean? +/// round_number(1.5, False) # What does `False` mean? +/// ``` +/// +/// Instead, refactor into separate implementations: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_up(number): +/// return ceil(number) +/// +/// +/// def round_down(number): +/// return floor(number) +/// +/// +/// round_up(1.5) +/// round_down(1.5) +/// ``` +/// +/// Or, refactor to use an `Enum`: +/// ```python +/// from enum import Enum +/// +/// +/// class RoundingMethod(Enum): +/// UP = 1 +/// DOWN = 2 +/// +/// +/// def round_number(value, method): +/// ... +/// ``` +/// +/// Or, make the argument a keyword-only argument: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number, *, up=True): +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, up=True) +/// round_number(1.5, up=False) +/// ``` +/// +/// ## References +/// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) +/// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) +#[violation] +pub struct BooleanDefaultValuePositionalArgument; + +impl Violation for BooleanDefaultValuePositionalArgument { + #[derive_message_formats] + fn message(&self) -> String { + format!("Boolean default positional argument in function definition") + } +} + +pub(crate) fn boolean_default_value_positional_argument( + checker: &mut Checker, + name: &str, + decorator_list: &[Decorator], + parameters: &Parameters, +) { + if is_allowed_func_def(name) { + return; + } + + if decorator_list.iter().any(|decorator| { + collect_call_path(&decorator.expression) + .is_some_and(|call_path| call_path.as_slice() == [name, "setter"]) + }) { + return; + } + + for ParameterWithDefault { + parameter, + default, + range: _, + } in parameters.posonlyargs.iter().chain(¶meters.args) + { + if default.as_ref().is_some_and(|default| is_boolean(default)) { + checker.diagnostics.push(Diagnostic::new( + BooleanDefaultValuePositionalArgument, + parameter.name.range(), + )); + } + } +} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs similarity index 60% rename from crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs rename to crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs index 6138fa67bd03d..0f6bf1fca7f9e 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs @@ -1,11 +1,9 @@ -use ruff_python_ast::Expr; - -use ruff_diagnostics::Violation; - +use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Expr, Ranged}; use crate::checkers::ast::Checker; -use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, allow_boolean_trap}; +use crate::rules::flake8_boolean_trap::helpers::{allow_boolean_trap, is_boolean}; /// ## What it does /// Checks for boolean positional arguments in function calls. @@ -17,44 +15,42 @@ use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, allow_boolean_t /// /// ## Example /// ```python -/// def foo(flag: bool) -> None: +/// def func(flag: bool) -> None: /// ... /// /// -/// foo(True) +/// func(True) /// ``` /// /// Use instead: /// ```python -/// def foo(flag: bool) -> None: +/// def func(flag: bool) -> None: /// ... /// /// -/// foo(flag=True) +/// func(flag=True) /// ``` /// /// ## References /// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) /// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) #[violation] -pub struct BooleanPositionalValueInFunctionCall; +pub struct BooleanPositionalValueInCall; -impl Violation for BooleanPositionalValueInFunctionCall { +impl Violation for BooleanPositionalValueInCall { #[derive_message_formats] fn message(&self) -> String { format!("Boolean positional value in function call") } } -pub(crate) fn check_boolean_positional_value_in_function_call( - checker: &mut Checker, - args: &[Expr], - func: &Expr, -) { +pub(crate) fn boolean_positional_value_in_call(checker: &mut Checker, args: &[Expr], func: &Expr) { if allow_boolean_trap(func) { return; } - for arg in args { - add_if_boolean(checker, arg, BooleanPositionalValueInFunctionCall.into()); + for arg in args.iter().filter(|arg| is_boolean(arg)) { + checker + .diagnostics + .push(Diagnostic::new(BooleanPositionalValueInCall, arg.range())); } } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs similarity index 60% rename from crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs rename to crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs index 29bea29ff2dd2..cfe52b282997f 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs @@ -1,4 +1,6 @@ -use ruff_python_ast::{self as ast, ArgWithDefault, Arguments, Constant, Decorator, Expr, Ranged}; +use ruff_python_ast::{ + self as ast, Constant, Decorator, Expr, ParameterWithDefault, Parameters, Ranged, +}; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Violation; @@ -9,16 +11,22 @@ use crate::checkers::ast::Checker; use crate::rules::flake8_boolean_trap::helpers::is_allowed_func_def; /// ## What it does -/// Checks for boolean positional arguments in function definitions. +/// Checks for the use of boolean positional arguments in function definitions, +/// as determined by the presence of a `bool` type hint. /// /// ## Why is this bad? /// Calling a function with boolean positional arguments is confusing as the -/// meaning of the boolean value is not clear to the caller, and to future +/// meaning of the boolean value is not clear to the caller and to future /// readers of the code. /// /// The use of a boolean will also limit the function to only two possible /// behaviors, which makes the function difficult to extend in the future. /// +/// Instead, consider refactoring into separate implementations for the +/// `True` and `False` cases, using an `Enum`, or making the argument a +/// keyword-only argument, to force callers to be explicit when providing +/// the argument. +/// /// ## Example /// ```python /// from math import ceil, floor @@ -63,24 +71,37 @@ use crate::rules::flake8_boolean_trap::helpers::is_allowed_func_def; /// ... /// ``` /// +/// Or, make the argument a keyword-only argument: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number: float, *, up: bool) -> int: +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, up=True) +/// round_number(1.5, up=False) +/// ``` +/// /// ## References /// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) /// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) #[violation] -pub struct BooleanPositionalArgInFunctionDefinition; +pub struct BooleanTypeHintPositionalArgument; -impl Violation for BooleanPositionalArgInFunctionDefinition { +impl Violation for BooleanTypeHintPositionalArgument { #[derive_message_formats] fn message(&self) -> String { - format!("Boolean positional arg in function definition") + format!("Boolean-typed positional argument in function definition") } } -pub(crate) fn check_positional_boolean_in_def( +pub(crate) fn boolean_type_hint_positional_argument( checker: &mut Checker, name: &str, decorator_list: &[Decorator], - arguments: &Arguments, + parameters: &Parameters, ) { if is_allowed_func_def(name) { return; @@ -88,39 +109,36 @@ pub(crate) fn check_positional_boolean_in_def( if decorator_list.iter().any(|decorator| { collect_call_path(&decorator.expression) - .map_or(false, |call_path| call_path.as_slice() == [name, "setter"]) + .is_some_and(|call_path| call_path.as_slice() == [name, "setter"]) }) { return; } - for ArgWithDefault { - def, + for ParameterWithDefault { + parameter, default: _, range: _, - } in arguments.posonlyargs.iter().chain(&arguments.args) + } in parameters.posonlyargs.iter().chain(¶meters.args) { - if def.annotation.is_none() { - continue; - } - let Some(expr) = &def.annotation else { + let Some(annotation) = parameter.annotation.as_ref() else { continue; }; // check for both bool (python class) and 'bool' (string annotation) - let hint = match expr.as_ref() { + let hint = match annotation.as_ref() { Expr::Name(name) => &name.id == "bool", Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) => value == "bool", _ => false, }; - if !hint { + if !hint || !checker.semantic().is_builtin("bool") { continue; } checker.diagnostics.push(Diagnostic::new( - BooleanPositionalArgInFunctionDefinition, - def.range(), + BooleanTypeHintPositionalArgument, + parameter.name.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs deleted file mode 100644 index 84575feb7fbf4..0000000000000 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs +++ /dev/null @@ -1,90 +0,0 @@ -use ruff_python_ast::{ArgWithDefault, Arguments, Decorator}; - -use ruff_diagnostics::Violation; -use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::call_path::collect_call_path; - -use crate::checkers::ast::Checker; -use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, is_allowed_func_def}; - -/// ## What it does -/// Checks for the use of booleans as default values in function definitions. -/// -/// ## Why is this bad? -/// Calling a function with boolean default means that the keyword argument -/// argument can be omitted, which makes the function call ambiguous. -/// -/// Instead, define the relevant argument as keyword-only. -/// -/// ## Example -/// ```python -/// from math import ceil, floor -/// -/// -/// def round_number(number: float, *, up: bool = True) -> int: -/// return ceil(number) if up else floor(number) -/// -/// -/// round_number(1.5) -/// round_number(1.5, up=False) -/// ``` -/// -/// Use instead: -/// ```python -/// from math import ceil, floor -/// -/// -/// def round_number(number: float, *, up: bool) -> int: -/// return ceil(number) if up else floor(number) -/// -/// -/// round_number(1.5, up=True) -/// round_number(1.5, up=False) -/// ``` -/// -/// ## References -/// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) -/// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) -#[violation] -pub struct BooleanDefaultValueInFunctionDefinition; - -impl Violation for BooleanDefaultValueInFunctionDefinition { - #[derive_message_formats] - fn message(&self) -> String { - format!("Boolean default value in function definition") - } -} - -pub(crate) fn check_boolean_default_value_in_function_definition( - checker: &mut Checker, - name: &str, - decorator_list: &[Decorator], - arguments: &Arguments, -) { - if is_allowed_func_def(name) { - return; - } - - if decorator_list.iter().any(|decorator| { - collect_call_path(&decorator.expression) - .map_or(false, |call_path| call_path.as_slice() == [name, "setter"]) - }) { - return; - } - - for ArgWithDefault { - def: _, - default, - range: _, - } in arguments.args.iter().chain(&arguments.posonlyargs) - { - let Some(default) = default else { - continue; - }; - add_if_boolean( - checker, - default, - BooleanDefaultValueInFunctionDefinition.into(), - ); - } -} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs index b40aa58dc5a0b..a9aae13b6785e 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs @@ -1,7 +1,7 @@ -pub(crate) use check_boolean_default_value_in_function_definition::*; -pub(crate) use check_boolean_positional_value_in_function_call::*; -pub(crate) use check_positional_boolean_in_def::*; +pub(crate) use boolean_default_value_positional_argument::*; +pub(crate) use boolean_positional_value_in_call::*; +pub(crate) use boolean_type_hint_positional_argument::*; -mod check_boolean_default_value_in_function_definition; -mod check_boolean_positional_value_in_function_call; -mod check_positional_boolean_in_def; +mod boolean_default_value_positional_argument; +mod boolean_positional_value_in_call; +mod boolean_type_hint_positional_argument; diff --git a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap index 2ee151ecb3005..b1c02ae6948a1 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap +++ b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap @@ -1,92 +1,92 @@ --- source: crates/ruff/src/rules/flake8_boolean_trap/mod.rs --- -FBT.py:4:5: FBT001 Boolean positional arg in function definition +FBT.py:4:5: FBT001 Boolean-typed positional argument in function definition | 2 | posonly_nohint, 3 | posonly_nonboolhint: int, 4 | posonly_boolhint: bool, - | ^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^ FBT001 5 | posonly_boolstrhint: "bool", 6 | /, | -FBT.py:5:5: FBT001 Boolean positional arg in function definition +FBT.py:5:5: FBT001 Boolean-typed positional argument in function definition | 3 | posonly_nonboolhint: int, 4 | posonly_boolhint: bool, 5 | posonly_boolstrhint: "bool", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^ FBT001 6 | /, 7 | offset, | -FBT.py:10:5: FBT001 Boolean positional arg in function definition +FBT.py:10:5: FBT001 Boolean-typed positional argument in function definition | 8 | posorkw_nonvalued_nohint, 9 | posorkw_nonvalued_nonboolhint: int, 10 | posorkw_nonvalued_boolhint: bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, | -FBT.py:11:5: FBT001 Boolean positional arg in function definition +FBT.py:11:5: FBT001 Boolean-typed positional argument in function definition | 9 | posorkw_nonvalued_nonboolhint: int, 10 | posorkw_nonvalued_boolhint: bool, 11 | posorkw_nonvalued_boolstrhint: "bool", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, | -FBT.py:14:5: FBT001 Boolean positional arg in function definition +FBT.py:14:5: FBT001 Boolean-typed positional argument in function definition | 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 15 | posorkw_boolvalued_boolstrhint: "bool" = True, 16 | posorkw_nonboolvalued_nohint=1, | -FBT.py:15:5: FBT001 Boolean positional arg in function definition +FBT.py:15:5: FBT001 Boolean-typed positional argument in function definition | 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, | -FBT.py:18:5: FBT001 Boolean positional arg in function definition +FBT.py:18:5: FBT001 Boolean-typed positional argument in function definition | 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, 18 | posorkw_nonboolvalued_boolhint: bool = 3, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 19 | posorkw_nonboolvalued_boolstrhint: "bool" = 4, 20 | *, | -FBT.py:19:5: FBT001 Boolean positional arg in function definition +FBT.py:19:5: FBT001 Boolean-typed positional argument in function definition | 17 | posorkw_nonboolvalued_nonboolhint: int = 2, 18 | posorkw_nonboolvalued_boolhint: bool = 3, 19 | posorkw_nonboolvalued_boolstrhint: "bool" = 4, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 20 | *, 21 | kwonly_nonvalued_nohint, | -FBT.py:85:19: FBT001 Boolean positional arg in function definition +FBT.py:87:19: FBT001 Boolean-typed positional argument in function definition | -84 | # FBT001: Boolean positional arg in function definition -85 | def foo(self, value: bool) -> None: - | ^^^^^^^^^^^ FBT001 -86 | pass +86 | # FBT001: Boolean positional arg in function definition +87 | def foo(self, value: bool) -> None: + | ^^^^^ FBT001 +88 | pass | diff --git a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap index 5a76f50142dcc..688254791d3a2 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap +++ b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap @@ -1,42 +1,42 @@ --- source: crates/ruff/src/rules/flake8_boolean_trap/mod.rs --- -FBT.py:12:31: FBT002 Boolean default value in function definition +FBT.py:12:5: FBT002 Boolean default positional argument in function definition | 10 | posorkw_nonvalued_boolhint: bool, 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, | -FBT.py:13:43: FBT002 Boolean default value in function definition +FBT.py:13:5: FBT002 Boolean default positional argument in function definition | 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, | -FBT.py:14:41: FBT002 Boolean default value in function definition +FBT.py:14:5: FBT002 Boolean default positional argument in function definition | 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 15 | posorkw_boolvalued_boolstrhint: "bool" = True, 16 | posorkw_nonboolvalued_nohint=1, | -FBT.py:15:46: FBT002 Boolean default value in function definition +FBT.py:15:5: FBT002 Boolean default positional argument in function definition | 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, | diff --git a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT003_FBT.py.snap b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT003_FBT.py.snap index d58728553edb8..9da28a09c33dc 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT003_FBT.py.snap +++ b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT003_FBT.py.snap @@ -34,6 +34,8 @@ FBT.py:69:38: FBT003 Boolean positional value in function call 68 | g_action.set_enabled(True) 69 | settings.set_enable_developer_extras(True) | ^^^^ FBT003 +70 | foo.is_(True) +71 | bar.is_not(False) | diff --git a/crates/ruff/src/rules/flake8_bugbear/mod.rs b/crates/ruff/src/rules/flake8_bugbear/mod.rs index 005fe03002145..717bb1ee3aed5 100644 --- a/crates/ruff/src/rules/flake8_bugbear/mod.rs +++ b/crates/ruff/src/rules/flake8_bugbear/mod.rs @@ -49,7 +49,6 @@ mod tests { #[test_case(Rule::UselessComparison, Path::new("B015.py"))] #[test_case(Rule::UselessContextlibSuppress, Path::new("B022.py"))] #[test_case(Rule::UselessExpression, Path::new("B018.py"))] - #[test_case(Rule::ZipWithoutExplicitStrict, Path::new("B905.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( @@ -61,8 +60,38 @@ mod tests { } #[test] - fn extend_immutable_calls() -> Result<()> { - let snapshot = "extend_immutable_calls".to_string(); + fn zip_without_explicit_strict() -> Result<()> { + let snapshot = "B905.py"; + let diagnostics = test_path( + Path::new("flake8_bugbear").join(snapshot).as_path(), + &Settings::for_rule(Rule::ZipWithoutExplicitStrict), + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } + + #[test] + fn extend_immutable_calls_arg_annotation() -> Result<()> { + let snapshot = "extend_immutable_calls_arg_annotation".to_string(); + let diagnostics = test_path( + Path::new("flake8_bugbear/B006_extended.py"), + &Settings { + flake8_bugbear: super::settings::Settings { + extend_immutable_calls: vec![ + "custom.ImmutableTypeA".to_string(), + "custom.ImmutableTypeB".to_string(), + ], + }, + ..Settings::for_rule(Rule::MutableArgumentDefault) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } + + #[test] + fn extend_immutable_calls_arg_default() -> Result<()> { + let snapshot = "extend_immutable_calls_arg_default".to_string(); let diagnostics = test_path( Path::new("flake8_bugbear/B008_extended.py"), &Settings { @@ -70,9 +99,10 @@ mod tests { extend_immutable_calls: vec![ "fastapi.Depends".to_string(), "fastapi.Query".to_string(), + "custom.ImmutableTypeA".to_string(), ], }, - ..Settings::for_rules(vec![Rule::FunctionCallInDefaultArgument]) + ..Settings::for_rule(Rule::FunctionCallInDefaultArgument) }, )?; assert_messages!(snapshot, diagnostics); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs index 681319c3996df..43307aa5c1f3f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Keyword, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -106,26 +106,21 @@ impl Violation for EmptyMethodWithoutAbstractDecorator { fn is_abc_class(bases: &[Expr], keywords: &[Keyword], semantic: &SemanticModel) -> bool { keywords.iter().any(|keyword| { - keyword.arg.as_ref().map_or(false, |arg| arg == "metaclass") + keyword.arg.as_ref().is_some_and(|arg| arg == "metaclass") && semantic .resolve_call_path(&keyword.value) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["abc", "ABCMeta"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["abc", "ABCMeta"])) }) || bases.iter().any(|base| { - semantic.resolve_call_path(base).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["abc", "ABC"]) - }) + semantic + .resolve_call_path(base) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["abc", "ABC"])) }) } fn is_empty_body(body: &[Stmt]) -> bool { body.iter().all(|stmt| match stmt { Stmt::Pass(_) => true, - Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => match value.as_ref() { + Stmt::Expr(ast::StmtExpr { value, range: _ }) => match value.as_ref() { Expr::Constant(ast::ExprConstant { value, .. }) => { matches!(value, Constant::Str(..) | Constant::Ellipsis) } @@ -141,14 +136,17 @@ pub(crate) fn abstract_base_class( checker: &mut Checker, stmt: &Stmt, name: &str, - bases: &[Expr], - keywords: &[Keyword], + arguments: Option<&Arguments>, body: &[Stmt], ) { - if bases.len() + keywords.len() != 1 { + let Some(Arguments { args, keywords, .. }) = arguments else { + return; + }; + + if args.len() + keywords.len() != 1 { return; } - if !is_abc_class(bases, keywords, checker.semantic()) { + if !is_abc_class(args, keywords, checker.semantic()) { return; } @@ -161,18 +159,12 @@ pub(crate) fn abstract_base_class( continue; } - let (Stmt::FunctionDef(ast::StmtFunctionDef { - decorator_list, - body, - name: method_name, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { + let Stmt::FunctionDef(ast::StmtFunctionDef { decorator_list, body, name: method_name, .. - })) = stmt + }) = stmt else { continue; }; diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs index 40de4922bfa53..776110f707904 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, ExprContext, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Ranged, Stmt}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -53,12 +53,15 @@ fn assertion_error(msg: Option<&Expr>) -> Stmt { ctx: ExprContext::Load, range: TextRange::default(), })), - args: if let Some(msg) = msg { - vec![msg.clone()] - } else { - vec![] + arguments: Arguments { + args: if let Some(msg) = msg { + vec![msg.clone()] + } else { + vec![] + }, + keywords: vec![], + range: TextRange::default(), }, - keywords: vec![], range: TextRange::default(), }))), cause: None, diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs index 57c0bd5e062b7..908fd6e7de548 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs @@ -1,10 +1,8 @@ use std::fmt; -use ruff_python_ast::{self as ast, Expr, Ranged, WithItem}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Expr, Ranged, WithItem}; use crate::checkers::ast::Checker; @@ -81,23 +79,24 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem]) for item in items { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments, range: _, }) = &item.context_expr else { return; }; - if args.len() != 1 { - return; - } + if item.optional_vars.is_some() { return; } + let [arg] = arguments.args.as_slice() else { + return; + }; + let Some(exception) = checker .semantic() - .resolve_call_path(args.first().unwrap()) + .resolve_call_path(arg) .and_then(|call_path| match call_path.as_slice() { ["", "Exception"] => Some(ExceptionKind::Exception), ["", "BaseException"] => Some(ExceptionKind::BaseException), @@ -113,10 +112,8 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem]) } else if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "raises"]) - }) - && find_keyword(keywords, "match").is_none() + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "raises"])) + && arguments.find_keyword("match").is_none() { AssertionKind::PytestRaises } else { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs index 16452049cfc54..61e99ed49126e 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs @@ -70,14 +70,14 @@ impl Violation for CachedInstanceMethod { } fn is_cache_func(expr: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { matches!(call_path.as_slice(), ["functools", "lru_cache" | "cache"]) }) } /// B019 pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Decorator]) { - if !checker.semantic().scope().kind.is_class() { + if !checker.semantic().current_scope().kind.is_class() { return; } for decorator in decorator_list { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs b/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs index 6f6fbe550aedf..f09a7f9a2a5cc 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs @@ -90,8 +90,7 @@ impl AlwaysAutofixableViolation for DuplicateHandlerException { #[derive_message_formats] fn message(&self) -> String { let DuplicateHandlerException { names } = self; - if names.len() == 1 { - let name = &names[0]; + if let [name] = names.as_slice() { format!("Exception handler with duplicate exception: `{name}`") } else { let names = names.iter().map(|name| format!("`{name}`")).join(", "); @@ -150,7 +149,9 @@ fn duplicate_handler_exceptions<'a>( if unique_elts.len() == 1 { checker.generator().expr(unique_elts[0]) } else { - checker.generator().expr(&type_pattern(unique_elts)) + // Multiple exceptions must always be parenthesized. This is done + // manually as the generator never parenthesizes lone tuples. + format!("({})", checker.generator().expr(&type_pattern(unique_elts))) }, expr.range(), ))); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs b/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs index 2deb444d37148..7441f8a9ebdff 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/f_string_docstring.rs @@ -50,7 +50,7 @@ pub(crate) fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) { let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt else { return; }; - if !value.is_joined_str_expr() { + if !value.is_f_string_expr() { return; } checker diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_in_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_in_argument_default.rs index 79949dd81e807..66c68f3fae532 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_in_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_in_argument_default.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, ArgWithDefault, Arguments, Expr, Ranged}; +use ruff_python_ast::{self as ast, Expr, ParameterWithDefault, Parameters, Ranged}; use ruff_text_size::TextRange; use ruff_diagnostics::Violation; @@ -7,7 +7,9 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::{compose_call_path, from_qualified_name, CallPath}; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; -use ruff_python_semantic::analyze::typing::{is_immutable_func, is_mutable_func}; +use ruff_python_semantic::analyze::typing::{ + is_immutable_annotation, is_immutable_func, is_mutable_func, +}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -20,6 +22,13 @@ use crate::checkers::ast::Checker; /// once, at definition time. The returned value will then be reused by all /// calls to the function, which can lead to unexpected behaviour. /// +/// Calls can be marked as an exception to this rule with the +/// [`flake8-bugbear.extend-immutable-calls`] configuration option. +/// +/// Arguments with immutable type annotations will be ignored by this rule. +/// Types outside of the standard library can be marked as immutable with the +/// [`flake8-bugbear.extend-immutable-calls`] configuration option as well. +/// /// ## Example /// ```python /// def create_list() -> list[int]: @@ -60,31 +69,28 @@ impl Violation for FunctionCallInDefaultArgument { } } -struct ArgumentDefaultVisitor<'a> { - semantic: &'a SemanticModel<'a>, - extend_immutable_calls: Vec>, +struct ArgumentDefaultVisitor<'a, 'b> { + semantic: &'a SemanticModel<'b>, + extend_immutable_calls: &'a [CallPath<'b>], diagnostics: Vec<(DiagnosticKind, TextRange)>, } -impl<'a> ArgumentDefaultVisitor<'a> { - fn new(model: &'a SemanticModel<'a>, extend_immutable_calls: Vec>) -> Self { +impl<'a, 'b> ArgumentDefaultVisitor<'a, 'b> { + fn new(semantic: &'a SemanticModel<'b>, extend_immutable_calls: &'a [CallPath<'b>]) -> Self { Self { - semantic: model, + semantic, extend_immutable_calls, diagnostics: Vec::new(), } } } -impl<'a, 'b> Visitor<'b> for ArgumentDefaultVisitor<'b> -where - 'b: 'a, -{ - fn visit_expr(&mut self, expr: &'b Expr) { +impl Visitor<'_> for ArgumentDefaultVisitor<'_, '_> { + fn visit_expr(&mut self, expr: &Expr) { match expr { Expr::Call(ast::ExprCall { func, .. }) => { if !is_mutable_func(func, self.semantic) - && !is_immutable_func(func, self.semantic, &self.extend_immutable_calls) + && !is_immutable_func(func, self.semantic, self.extend_immutable_calls) { self.diagnostics.push(( FunctionCallInDefaultArgument { @@ -105,7 +111,7 @@ where } /// B008 -pub(crate) fn function_call_in_argument_default(checker: &mut Checker, arguments: &Arguments) { +pub(crate) fn function_call_in_argument_default(checker: &mut Checker, parameters: &Parameters) { // Map immutable calls to (module, member) format. let extend_immutable_calls: Vec = checker .settings @@ -114,25 +120,28 @@ pub(crate) fn function_call_in_argument_default(checker: &mut Checker, arguments .iter() .map(|target| from_qualified_name(target)) .collect(); - let diagnostics = { - let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), extend_immutable_calls); - for ArgWithDefault { - default, - def: _, - range: _, - } in arguments - .posonlyargs - .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) - { - if let Some(expr) = &default { + + let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), &extend_immutable_calls); + for ParameterWithDefault { + default, + parameter, + range: _, + } in parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + { + if let Some(expr) = &default { + if !parameter.annotation.as_ref().is_some_and(|expr| { + is_immutable_annotation(expr, checker.semantic(), &extend_immutable_calls) + }) { visitor.visit_expr(expr); } } - visitor.diagnostics - }; - for (check, range) in diagnostics { + } + + for (check, range) in visitor.diagnostics { checker.diagnostics.push(Diagnostic::new(check, range)); } } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs index 062079e1928c2..7cbb231fbd322 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/function_uses_loop_variable.rs @@ -1,11 +1,9 @@ -use ruff_python_ast::{self as ast, Comprehension, Expr, ExprContext, Ranged, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::includes_arg_name; use ruff_python_ast::types::Node; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::{self as ast, Arguments, Comprehension, Expr, ExprContext, Ranged, Stmt}; use crate::checkers::ast::Checker; @@ -86,8 +84,9 @@ struct SuspiciousVariablesVisitor<'a> { impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { args, body, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, .. }) => { + Stmt::FunctionDef(ast::StmtFunctionDef { + parameters, body, .. + }) => { // Collect all loaded variable names. let mut visitor = LoadedNamesVisitor::default(); visitor.visit_body(body); @@ -99,7 +98,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { return false; } - if includes_arg_name(&loaded.id, args) { + if parameters.includes(&loaded.id) { return false; } @@ -126,8 +125,12 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { match expr { Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) => { match func.as_ref() { @@ -157,7 +160,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { } for keyword in keywords { - if keyword.arg.as_ref().map_or(false, |arg| arg == "key") + if keyword.arg.as_ref().is_some_and(|arg| arg == "key") && keyword.value.is_lambda_expr() { self.safe_functions.push(&keyword.value); @@ -165,7 +168,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { } } Expr::Lambda(ast::ExprLambda { - args, + parameters, body, range: _, }) => { @@ -181,7 +184,10 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> { return false; } - if includes_arg_name(&loaded.id, args) { + if parameters + .as_ref() + .is_some_and(|parameters| parameters.includes(&loaded.id)) + { return false; } @@ -230,7 +236,7 @@ struct AssignedNamesVisitor<'a> { /// `Visitor` to collect all used identifiers in a statement. impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { - if matches!(stmt, Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_)) { + if stmt.is_function_def_stmt() { // Don't recurse. return; } @@ -245,8 +251,7 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> { } Stmt::AugAssign(ast::StmtAugAssign { target, .. }) | Stmt::AnnAssign(ast::StmtAnnAssign { target, .. }) - | Stmt::For(ast::StmtFor { target, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { target, .. }) => { + | Stmt::For(ast::StmtFor { target, .. }) => { let mut visitor = NamesFromAssignmentsVisitor::default(); visitor.visit_expr(target); self.names.extend(visitor.names); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs index 94de14785c40d..c7c5944c81aa8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs @@ -64,7 +64,7 @@ pub(crate) fn getattr_with_constant( return; }; let Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = arg else { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs b/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs index df83409f2eac9..5c5ca90cb7310 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/jump_statement_in_finally.rs @@ -69,16 +69,12 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) { )); } match stmt { - Stmt::While(ast::StmtWhile { body, .. }) - | Stmt::For(ast::StmtFor { body, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, .. }) => { + Stmt::While(ast::StmtWhile { body, .. }) | Stmt::For(ast::StmtFor { body, .. }) => { walk_stmt(checker, body, Stmt::is_return_stmt); } Stmt::If(ast::StmtIf { body, .. }) | Stmt::Try(ast::StmtTry { body, .. }) - | Stmt::TryStar(ast::StmtTryStar { body, .. }) - | Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + | Stmt::With(ast::StmtWith { body, .. }) => { walk_stmt(checker, body, f); } Stmt::Match(ast::StmtMatch { cases, .. }) => { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs b/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs index e26f4284ffcff..45439b11418c8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/loop_variable_overrides_iterator.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, ArgWithDefault, Expr, Ranged}; +use ruff_python_ast::{self as ast, Expr, ParameterWithDefault, Ranged}; use rustc_hash::FxHashMap; use ruff_diagnostics::{Diagnostic, Violation}; @@ -71,22 +71,25 @@ where } } Expr::Lambda(ast::ExprLambda { - args, + parameters, body, range: _, }) => { visitor::walk_expr(self, body); - for ArgWithDefault { - def, - default: _, - range: _, - } in args - .posonlyargs - .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) - { - self.names.remove(def.arg.as_str()); + + if let Some(parameters) = parameters { + for ParameterWithDefault { + parameter, + default: _, + range: _, + } in parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + { + self.names.remove(parameter.name.as_str()); + } } } _ => visitor::walk_expr(self, expr), diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs index beb9ecf07ebdd..f00944d1e813d 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs @@ -1,10 +1,16 @@ -use ruff_python_ast::{ArgWithDefault, Arguments, Ranged}; - -use ruff_diagnostics::{Diagnostic, Violation}; +use ast::call_path::{from_qualified_name, CallPath}; +use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::helpers::is_docstring_stmt; +use ruff_python_ast::{self as ast, Expr, Parameter, ParameterWithDefault, Ranged}; +use ruff_python_codegen::{Generator, Stylist}; +use ruff_python_index::Indexer; use ruff_python_semantic::analyze::typing::{is_immutable_annotation, is_mutable_expr}; +use ruff_python_trivia::{indentation_at_offset, textwrap}; +use ruff_source_file::Locator; use crate::checkers::ast::Checker; +use crate::registry::AsRule; /// ## What it does /// Checks for uses of mutable objects as function argument defaults. @@ -20,6 +26,10 @@ use crate::checkers::ast::Checker; /// default, and initialize a new mutable object inside the function body /// for each call. /// +/// Arguments with immutable type annotations will be ignored by this rule. +/// Types outside of the standard library can be marked as immutable with the +/// [`flake8-bugbear.extend-immutable-calls`] configuration option. +/// /// ## Example /// ```python /// def add_to_list(item, some_list=[]): @@ -44,43 +54,135 @@ use crate::checkers::ast::Checker; /// l2 = add_to_list(1) # [1] /// ``` /// +/// ## Options +/// - `flake8-bugbear.extend-immutable-calls` +/// /// ## References /// - [Python documentation: Default Argument Values](https://docs.python.org/3/tutorial/controlflow.html#default-argument-values) #[violation] pub struct MutableArgumentDefault; impl Violation for MutableArgumentDefault { + const AUTOFIX: AutofixKind = AutofixKind::Sometimes; + #[derive_message_formats] fn message(&self) -> String { format!("Do not use mutable data structures for argument defaults") } + fn autofix_title(&self) -> Option { + Some(format!("Replace with `None`; initialize within function")) + } } /// B006 -pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Arguments) { +pub(crate) fn mutable_argument_default(checker: &mut Checker, function_def: &ast::StmtFunctionDef) { // Scan in reverse order to right-align zip(). - for ArgWithDefault { - def, + for ParameterWithDefault { + parameter, default, range: _, - } in arguments + } in function_def + .parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(&function_def.parameters.args) + .chain(&function_def.parameters.kwonlyargs) { let Some(default) = default else { continue; }; + let extend_immutable_calls: Vec = checker + .settings + .flake8_bugbear + .extend_immutable_calls + .iter() + .map(|target| from_qualified_name(target)) + .collect(); + if is_mutable_expr(default, checker.semantic()) - && !def.annotation.as_ref().map_or(false, |expr| { - is_immutable_annotation(expr, checker.semantic()) + && !parameter.annotation.as_ref().is_some_and(|expr| { + is_immutable_annotation(expr, checker.semantic(), extend_immutable_calls.as_slice()) }) { - checker - .diagnostics - .push(Diagnostic::new(MutableArgumentDefault, default.range())); + let mut diagnostic = Diagnostic::new(MutableArgumentDefault, default.range()); + + // If the function body is on the same line as the function def, do not fix + if checker.patch(diagnostic.kind.rule()) { + if let Some(fix) = move_initialization( + function_def, + parameter, + default, + checker.locator(), + checker.stylist(), + checker.indexer(), + checker.generator(), + ) { + diagnostic.set_fix(fix); + } + } + checker.diagnostics.push(diagnostic); } } } + +/// Generate a [`Fix`] to move a mutable argument default initialization +/// into the function body. +fn move_initialization( + function_def: &ast::StmtFunctionDef, + parameter: &Parameter, + default: &Expr, + locator: &Locator, + stylist: &Stylist, + indexer: &Indexer, + generator: Generator, +) -> Option { + let mut body = function_def.body.iter(); + + let statement = body.next()?; + if indexer.in_multi_statement_line(statement, locator) { + return None; + } + + // Determine the indentation depth of the function body. + let indentation = indentation_at_offset(statement.start(), locator)?; + + // Set the default argument value to `None`. + let default_edit = Edit::range_replacement("None".to_string(), default.range()); + + // Add an `if`, to set the argument to its original value if still `None`. + let mut content = String::new(); + content.push_str(&format!("if {} is None:", parameter.name.as_str())); + content.push_str(stylist.line_ending().as_str()); + content.push_str(stylist.indentation()); + content.push_str(&format!( + "{} = {}", + parameter.name.as_str(), + generator.expr(default) + )); + content.push_str(stylist.line_ending().as_str()); + + // Indent the edit to match the body indentation. + let content = textwrap::indent(&content, indentation).to_string(); + + let initialization_edit = if is_docstring_stmt(statement) { + // If the first statement in the function is a docstring, insert _after_ it. + if let Some(statement) = body.next() { + // If there's a second statement, insert _before_ it, but ensure this isn't a + // multi-statement line. + if indexer.in_multi_statement_line(statement, locator) { + return None; + } + Edit::insertion(content, locator.line_start(statement.start())) + } else { + // If the docstring is the only statement, insert _before_ it. + Edit::insertion(content, locator.full_line_end(statement.end())) + } + } else { + // Otherwise, insert before the first statement. + let at = locator.line_start(statement.start()); + Edit::insertion(content, at) + }; + + Some(Fix::manual_edits(default_edit, [initialization_edit])) +} diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs index b3e561a54f256..c964e54d682cc 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -38,22 +36,20 @@ impl Violation for NoExplicitStacklevel { } /// B028 -pub(crate) fn no_explicit_stacklevel(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn no_explicit_stacklevel(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["warnings", "warn"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["warnings", "warn"])) { return; } - if find_keyword(keywords, "stacklevel").is_some() { + if call.arguments.find_keyword("stacklevel").is_some() { return; } checker .diagnostics - .push(Diagnostic::new(NoExplicitStacklevel, func.range())); + .push(Diagnostic::new(NoExplicitStacklevel, call.func.range())); } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs b/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs index a9145227339ab..7af198e177e4c 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/raise_without_from_inside_except.rs @@ -87,7 +87,7 @@ pub(crate) fn raise_without_from_inside_except( if let Some(name) = name { if exc .as_name_expr() - .map_or(false, |ast::ExprName { id, .. }| name == id) + .is_some_and(|ast::ExprName { id, .. }| name == id) { continue; } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/re_sub_positional_args.rs b/crates/ruff/src/rules/flake8_bugbear/rules/re_sub_positional_args.rs index 13f547391b19b..ebf89e57e49de 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/re_sub_positional_args.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/re_sub_positional_args.rs @@ -68,7 +68,7 @@ pub(crate) fn re_sub_positional_args(checker: &mut Checker, call: &ast::ExprCall return; }; - if call.args.len() > method.num_args() { + if call.arguments.args.len() > method.num_args() { checker.diagnostics.push(Diagnostic::new( ReSubPositionalArgs { method }, call.range(), diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs b/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs index e9fd4bb1556ca..844c32d123dd8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs @@ -79,7 +79,6 @@ pub(crate) fn redundant_tuple_in_exception_handler( type_.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] diagnostic.set_fix(Fix::automatic(Edit::range_replacement( checker.generator().expr(elt), type_.range(), diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs index 566e6345df484..1ffe1b59050d8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs @@ -313,9 +313,7 @@ pub(crate) fn reuse_of_groupby_generator( if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["itertools", "groupby"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["itertools", "groupby"])) { return; } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs index 369391d5ab5a7..9bb1802b857b2 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs @@ -88,7 +88,7 @@ pub(crate) fn setattr_with_constant( if !is_identifier(name) { return; } - if is_mangled_private(name.as_str()) { + if is_mangled_private(name) { return; } // We can only replace a `setattr` call (which is an `Expr`) with an assignment @@ -97,7 +97,7 @@ pub(crate) fn setattr_with_constant( if let Stmt::Expr(ast::StmtExpr { value: child, range: _, - }) = checker.semantic().stmt() + }) = checker.semantic().current_statement() { if expr == child.as_ref() { let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range()); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs index d9532a927b8f6..eefcf16bd7d5e 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs @@ -68,13 +68,13 @@ pub(crate) fn unreliable_callable_check( return; }; let Expr::Constant(ast::ExprConstant { - value: Constant::Str(string), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = attr else { return; }; - if string != "__call__" { + if value != "__call__" { return; } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs index dc2553d2007d3..d8b37dac1abca 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs @@ -1,9 +1,9 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_python_ast::{helpers, visitor}; use crate::checkers::ast::Checker; @@ -105,16 +105,16 @@ where } /// B007 -pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr, body: &[Stmt]) { +pub(crate) fn unused_loop_control_variable(checker: &mut Checker, stmt_for: &ast::StmtFor) { let control_names = { let mut finder = NameFinder::new(); - finder.visit_expr(target); + finder.visit_expr(stmt_for.target.as_ref()); finder.names }; let used_names = { let mut finder = NameFinder::new(); - for stmt in body { + for stmt in &stmt_for.body { finder.visit_stmt(stmt); } finder.names @@ -132,9 +132,10 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr, } // Avoid fixing any variables that _may_ be used, but undetectably so. - let certainty = Certainty::from(!helpers::uses_magic_variable_access(body, |id| { - checker.semantic().is_builtin(id) - })); + let certainty = + Certainty::from(!helpers::uses_magic_variable_access(&stmt_for.body, |id| { + checker.semantic().is_builtin(id) + })); // Attempt to rename the variable by prepending an underscore, but avoid // applying the fix if doing so wouldn't actually cause us to ignore the @@ -159,11 +160,11 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr, if certainty.into() { // Avoid fixing if the variable, or any future bindings to the variable, are // used _after_ the loop. - let scope = checker.semantic().scope(); + let scope = checker.semantic().current_scope(); if scope .get_all(name) .map(|binding_id| checker.semantic().binding(binding_id)) - .filter(|binding| binding.range.start() >= expr.range().start()) + .filter(|binding| binding.start() >= expr.start()) .all(|binding| !binding.is_used()) { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs index 5d04ab4179fb4..207f452f9c567 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs @@ -59,9 +59,7 @@ pub(crate) fn useless_contextlib_suppress( && checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["contextlib", "suppress"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["contextlib", "suppress"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs index e71e87c8c0b6a..cdef77fcd68ad 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs @@ -54,7 +54,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) { // Ignore strings, to avoid false positives with docstrings. if matches!( value, - Expr::JoinedStr(_) + Expr::FString(_) | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Ellipsis, .. diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs index 4f875938ba65a..c1ca58886be85 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -41,24 +40,20 @@ impl Violation for ZipWithoutExplicitStrict { } /// B905 -pub(crate) fn zip_without_explicit_strict( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], - kwargs: &[Keyword], -) { - if let Expr::Name(ast::ExprName { id, .. }) = func { +pub(crate) fn zip_without_explicit_strict(checker: &mut Checker, call: &ast::ExprCall) { + if let Expr::Name(ast::ExprName { id, .. }) = call.func.as_ref() { if id == "zip" && checker.semantic().is_builtin("zip") - && find_keyword(kwargs, "strict").is_none() - && !args + && call.arguments.find_keyword("strict").is_none() + && !call + .arguments + .args .iter() .any(|arg| is_infinite_iterator(arg, checker.semantic())) { checker .diagnostics - .push(Diagnostic::new(ZipWithoutExplicitStrict, expr.range())); + .push(Diagnostic::new(ZipWithoutExplicitStrict, call.range())); } } } @@ -68,15 +63,14 @@ pub(crate) fn zip_without_explicit_strict( fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: Arguments { args, keywords, .. }, .. }) = &arg else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { + semantic.resolve_call_path(func).is_some_and(|call_path| { match call_path.as_slice() { ["itertools", "cycle" | "count"] => true, ["itertools", "repeat"] => { @@ -92,7 +86,7 @@ fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool { // Ex) `iterools.repeat(1, times=None)` for keyword in keywords { - if keyword.arg.as_ref().map_or(false, |name| name == "times") { + if keyword.arg.as_ref().is_some_and(|name| name == "times") { if is_const_none(&keyword.value) { return true; } diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B006_B006_B008.py.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B006_B006_B008.py.snap index f1fc165498682..b98badffde675 100644 --- a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B006_B006_B008.py.snap +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B006_B006_B008.py.snap @@ -1,113 +1,479 @@ --- source: crates/ruff/src/rules/flake8_bugbear/mod.rs --- -B006_B008.py:63:25: B006 Do not use mutable data structures for argument defaults +B006_B008.py:63:25: B006 [*] Do not use mutable data structures for argument defaults | 63 | def this_is_wrong(value=[1, 2, 3]): | ^^^^^^^^^ B006 64 | ... | + = help: Replace with `None`; initialize within function -B006_B008.py:67:30: B006 Do not use mutable data structures for argument defaults +ℹ Possible fix +60 60 | # Flag mutable literals/comprehensions +61 61 | +62 62 | +63 |-def this_is_wrong(value=[1, 2, 3]): + 63 |+def this_is_wrong(value=None): + 64 |+ if value is None: + 65 |+ value = [1, 2, 3] +64 66 | ... +65 67 | +66 68 | + +B006_B008.py:67:30: B006 [*] Do not use mutable data structures for argument defaults | 67 | def this_is_also_wrong(value={}): | ^^ B006 68 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +64 64 | ... +65 65 | +66 66 | +67 |-def this_is_also_wrong(value={}): + 67 |+def this_is_also_wrong(value=None): + 68 |+ if value is None: + 69 |+ value = {} +68 70 | ... +69 71 | +70 72 | -B006_B008.py:71:20: B006 Do not use mutable data structures for argument defaults +B006_B008.py:73:52: B006 [*] Do not use mutable data structures for argument defaults | -71 | def and_this(value=set()): - | ^^^^^ B006 -72 | ... +71 | class Foo: +72 | @staticmethod +73 | def this_is_also_wrong_and_more_indented(value={}): + | ^^ B006 +74 | pass | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +70 70 | +71 71 | class Foo: +72 72 | @staticmethod +73 |- def this_is_also_wrong_and_more_indented(value={}): + 73 |+ def this_is_also_wrong_and_more_indented(value=None): + 74 |+ if value is None: + 75 |+ value = {} +74 76 | pass +75 77 | +76 78 | -B006_B008.py:75:20: B006 Do not use mutable data structures for argument defaults +B006_B008.py:77:31: B006 [*] Do not use mutable data structures for argument defaults | -75 | def this_too(value=collections.OrderedDict()): - | ^^^^^^^^^^^^^^^^^^^^^^^^^ B006 -76 | ... +77 | def multiline_arg_wrong(value={ + | _______________________________^ +78 | | +79 | | }): + | |_^ B006 +80 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +74 74 | pass +75 75 | +76 76 | +77 |-def multiline_arg_wrong(value={ +78 |- +79 |-}): + 77 |+def multiline_arg_wrong(value=None): + 78 |+ if value is None: + 79 |+ value = {} +80 80 | ... +81 81 | +82 82 | def single_line_func_wrong(value = {}): ... -B006_B008.py:79:32: B006 Do not use mutable data structures for argument defaults +B006_B008.py:82:36: B006 Do not use mutable data structures for argument defaults | -79 | async def async_this_too(value=collections.defaultdict()): - | ^^^^^^^^^^^^^^^^^^^^^^^^^ B006 80 | ... +81 | +82 | def single_line_func_wrong(value = {}): ... + | ^^ B006 | + = help: Replace with `None`; initialize within function -B006_B008.py:83:26: B006 Do not use mutable data structures for argument defaults +B006_B008.py:85:20: B006 [*] Do not use mutable data structures for argument defaults | -83 | def dont_forget_me(value=collections.deque()): - | ^^^^^^^^^^^^^^^^^^^ B006 -84 | ... +85 | def and_this(value=set()): + | ^^^^^ B006 +86 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +82 82 | def single_line_func_wrong(value = {}): ... +83 83 | +84 84 | +85 |-def and_this(value=set()): + 85 |+def and_this(value=None): + 86 |+ if value is None: + 87 |+ value = set() +86 88 | ... +87 89 | +88 90 | -B006_B008.py:88:46: B006 Do not use mutable data structures for argument defaults +B006_B008.py:89:20: B006 [*] Do not use mutable data structures for argument defaults | -87 | # N.B. we're also flagging the function call in the comprehension -88 | def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]): - | ^^^^^^^^^^^^^^^^^^^^^^^^ B006 -89 | pass +89 | def this_too(value=collections.OrderedDict()): + | ^^^^^^^^^^^^^^^^^^^^^^^^^ B006 +90 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +86 86 | ... +87 87 | +88 88 | +89 |-def this_too(value=collections.OrderedDict()): + 89 |+def this_too(value=None): + 90 |+ if value is None: + 91 |+ value = collections.OrderedDict() +90 92 | ... +91 93 | +92 94 | -B006_B008.py:92:46: B006 Do not use mutable data structures for argument defaults +B006_B008.py:93:32: B006 [*] Do not use mutable data structures for argument defaults | -92 | def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}): - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ B006 -93 | pass +93 | async def async_this_too(value=collections.defaultdict()): + | ^^^^^^^^^^^^^^^^^^^^^^^^^ B006 +94 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +90 90 | ... +91 91 | +92 92 | +93 |-async def async_this_too(value=collections.defaultdict()): + 93 |+async def async_this_too(value=None): + 94 |+ if value is None: + 95 |+ value = collections.defaultdict() +94 96 | ... +95 97 | +96 98 | -B006_B008.py:96:45: B006 Do not use mutable data structures for argument defaults +B006_B008.py:97:26: B006 [*] Do not use mutable data structures for argument defaults | -96 | def set_comprehension_also_not_okay(default={i**2 for i in range(3)}): - | ^^^^^^^^^^^^^^^^^^^^^^^^ B006 -97 | pass +97 | def dont_forget_me(value=collections.deque()): + | ^^^^^^^^^^^^^^^^^^^ B006 +98 | ... | + = help: Replace with `None`; initialize within function -B006_B008.py:100:33: B006 Do not use mutable data structures for argument defaults +ℹ Possible fix +94 94 | ... +95 95 | +96 96 | +97 |-def dont_forget_me(value=collections.deque()): + 97 |+def dont_forget_me(value=None): + 98 |+ if value is None: + 99 |+ value = collections.deque() +98 100 | ... +99 101 | +100 102 | + +B006_B008.py:102:46: B006 [*] Do not use mutable data structures for argument defaults + | +101 | # N.B. we're also flagging the function call in the comprehension +102 | def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]): + | ^^^^^^^^^^^^^^^^^^^^^^^^ B006 +103 | pass + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +99 99 | +100 100 | +101 101 | # N.B. we're also flagging the function call in the comprehension +102 |-def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]): + 102 |+def list_comprehension_also_not_okay(default=None): + 103 |+ if default is None: + 104 |+ default = [i ** 2 for i in range(3)] +103 105 | pass +104 106 | +105 107 | + +B006_B008.py:106:46: B006 [*] Do not use mutable data structures for argument defaults + | +106 | def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ B006 +107 | pass + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +103 103 | pass +104 104 | +105 105 | +106 |-def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}): + 106 |+def dict_comprehension_also_not_okay(default=None): + 107 |+ if default is None: + 108 |+ default = {i: i ** 2 for i in range(3)} +107 109 | pass +108 110 | +109 111 | + +B006_B008.py:110:45: B006 [*] Do not use mutable data structures for argument defaults | -100 | def kwonlyargs_mutable(*, value=[]): +110 | def set_comprehension_also_not_okay(default={i**2 for i in range(3)}): + | ^^^^^^^^^^^^^^^^^^^^^^^^ B006 +111 | pass + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +107 107 | pass +108 108 | +109 109 | +110 |-def set_comprehension_also_not_okay(default={i**2 for i in range(3)}): + 110 |+def set_comprehension_also_not_okay(default=None): + 111 |+ if default is None: + 112 |+ default = {i ** 2 for i in range(3)} +111 113 | pass +112 114 | +113 115 | + +B006_B008.py:114:33: B006 [*] Do not use mutable data structures for argument defaults + | +114 | def kwonlyargs_mutable(*, value=[]): | ^^ B006 -101 | ... +115 | ... | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +111 111 | pass +112 112 | +113 113 | +114 |-def kwonlyargs_mutable(*, value=[]): + 114 |+def kwonlyargs_mutable(*, value=None): + 115 |+ if value is None: + 116 |+ value = [] +115 117 | ... +116 118 | +117 119 | -B006_B008.py:221:20: B006 Do not use mutable data structures for argument defaults +B006_B008.py:239:20: B006 [*] Do not use mutable data structures for argument defaults | -219 | # B006 and B008 -220 | # We should handle arbitrary nesting of these B008. -221 | def nested_combo(a=[float(3), dt.datetime.now()]): +237 | # B006 and B008 +238 | # We should handle arbitrary nesting of these B008. +239 | def nested_combo(a=[float(3), dt.datetime.now()]): | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B006 -222 | pass +240 | pass | + = help: Replace with `None`; initialize within function -B006_B008.py:254:27: B006 Do not use mutable data structures for argument defaults +ℹ Possible fix +236 236 | +237 237 | # B006 and B008 +238 238 | # We should handle arbitrary nesting of these B008. +239 |-def nested_combo(a=[float(3), dt.datetime.now()]): + 239 |+def nested_combo(a=None): + 240 |+ if a is None: + 241 |+ a = [float(3), dt.datetime.now()] +240 242 | pass +241 243 | +242 244 | + +B006_B008.py:276:27: B006 [*] Do not use mutable data structures for argument defaults | -253 | def mutable_annotations( -254 | a: list[int] | None = [], +275 | def mutable_annotations( +276 | a: list[int] | None = [], | ^^ B006 -255 | b: Optional[Dict[int, int]] = {}, -256 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +277 | b: Optional[Dict[int, int]] = {}, +278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +273 273 | +274 274 | +275 275 | def mutable_annotations( +276 |- a: list[int] | None = [], + 276 |+ a: list[int] | None = None, +277 277 | b: Optional[Dict[int, int]] = {}, +278 278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +279 279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +280 280 | ): + 281 |+ if a is None: + 282 |+ a = [] +281 283 | pass +282 284 | +283 285 | -B006_B008.py:255:35: B006 Do not use mutable data structures for argument defaults +B006_B008.py:277:35: B006 [*] Do not use mutable data structures for argument defaults | -253 | def mutable_annotations( -254 | a: list[int] | None = [], -255 | b: Optional[Dict[int, int]] = {}, +275 | def mutable_annotations( +276 | a: list[int] | None = [], +277 | b: Optional[Dict[int, int]] = {}, | ^^ B006 -256 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), -257 | ): +278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), | + = help: Replace with `None`; initialize within function -B006_B008.py:256:62: B006 Do not use mutable data structures for argument defaults +ℹ Possible fix +274 274 | +275 275 | def mutable_annotations( +276 276 | a: list[int] | None = [], +277 |- b: Optional[Dict[int, int]] = {}, + 277 |+ b: Optional[Dict[int, int]] = None, +278 278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +279 279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +280 280 | ): + 281 |+ if b is None: + 282 |+ b = {} +281 283 | pass +282 284 | +283 285 | + +B006_B008.py:278:62: B006 [*] Do not use mutable data structures for argument defaults | -254 | a: list[int] | None = [], -255 | b: Optional[Dict[int, int]] = {}, -256 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +276 | a: list[int] | None = [], +277 | b: Optional[Dict[int, int]] = {}, +278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), | ^^^^^ B006 -257 | ): -258 | pass +279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +280 | ): + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +275 275 | def mutable_annotations( +276 276 | a: list[int] | None = [], +277 277 | b: Optional[Dict[int, int]] = {}, +278 |- c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), + 278 |+ c: Annotated[Union[Set[str], abc.Sized], "annotation"] = None, +279 279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +280 280 | ): + 281 |+ if c is None: + 282 |+ c = set() +281 283 | pass +282 284 | +283 285 | + +B006_B008.py:279:80: B006 [*] Do not use mutable data structures for argument defaults + | +277 | b: Optional[Dict[int, int]] = {}, +278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), + | ^^^^^ B006 +280 | ): +281 | pass + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +276 276 | a: list[int] | None = [], +277 277 | b: Optional[Dict[int, int]] = {}, +278 278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), +279 |- d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(), + 279 |+ d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = None, +280 280 | ): + 281 |+ if d is None: + 282 |+ d = set() +281 283 | pass +282 284 | +283 285 | + +B006_B008.py:284:52: B006 [*] Do not use mutable data structures for argument defaults + | +284 | def single_line_func_wrong(value: dict[str, str] = {}): + | ^^ B006 +285 | """Docstring""" + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +281 281 | pass +282 282 | +283 283 | +284 |-def single_line_func_wrong(value: dict[str, str] = {}): + 284 |+def single_line_func_wrong(value: dict[str, str] = None): +285 285 | """Docstring""" + 286 |+ if value is None: + 287 |+ value = {} +286 288 | +287 289 | +288 290 | def single_line_func_wrong(value: dict[str, str] = {}): + +B006_B008.py:288:52: B006 [*] Do not use mutable data structures for argument defaults + | +288 | def single_line_func_wrong(value: dict[str, str] = {}): + | ^^ B006 +289 | """Docstring""" +290 | ... + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +285 285 | """Docstring""" +286 286 | +287 287 | +288 |-def single_line_func_wrong(value: dict[str, str] = {}): + 288 |+def single_line_func_wrong(value: dict[str, str] = None): +289 289 | """Docstring""" + 290 |+ if value is None: + 291 |+ value = {} +290 292 | ... +291 293 | +292 294 | + +B006_B008.py:293:52: B006 Do not use mutable data structures for argument defaults + | +293 | def single_line_func_wrong(value: dict[str, str] = {}): + | ^^ B006 +294 | """Docstring"""; ... + | + = help: Replace with `None`; initialize within function + +B006_B008.py:297:52: B006 Do not use mutable data structures for argument defaults + | +297 | def single_line_func_wrong(value: dict[str, str] = {}): + | ^^ B006 +298 | """Docstring"""; \ +299 | ... + | + = help: Replace with `None`; initialize within function + +B006_B008.py:302:52: B006 [*] Do not use mutable data structures for argument defaults + | +302 | def single_line_func_wrong(value: dict[str, str] = { + | ____________________________________________________^ +303 | | # This is a comment +304 | | }): + | |_^ B006 +305 | """Docstring""" + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +299 299 | ... +300 300 | +301 301 | +302 |-def single_line_func_wrong(value: dict[str, str] = { +303 |- # This is a comment +304 |-}): + 302 |+def single_line_func_wrong(value: dict[str, str] = None): +305 303 | """Docstring""" + 304 |+ if value is None: + 305 |+ value = {} +306 306 | +307 307 | +308 308 | def single_line_func_wrong(value: dict[str, str] = {}) \ + +B006_B008.py:308:52: B006 Do not use mutable data structures for argument defaults + | +308 | def single_line_func_wrong(value: dict[str, str] = {}) \ + | ^^ B006 +309 | : \ +310 | """Docstring""" | + = help: Replace with `None`; initialize within function diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B008_B006_B008.py.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B008_B006_B008.py.snap index 36a464813a00c..cae75c719a300 100644 --- a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B008_B006_B008.py.snap +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B008_B006_B008.py.snap @@ -1,83 +1,83 @@ --- source: crates/ruff/src/rules/flake8_bugbear/mod.rs --- -B006_B008.py:88:61: B008 Do not perform function call `range` in argument defaults - | -87 | # N.B. we're also flagging the function call in the comprehension -88 | def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]): - | ^^^^^^^^ B008 -89 | pass - | +B006_B008.py:102:61: B008 Do not perform function call `range` in argument defaults + | +101 | # N.B. we're also flagging the function call in the comprehension +102 | def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]): + | ^^^^^^^^ B008 +103 | pass + | -B006_B008.py:92:64: B008 Do not perform function call `range` in argument defaults - | -92 | def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}): - | ^^^^^^^^ B008 -93 | pass - | +B006_B008.py:106:64: B008 Do not perform function call `range` in argument defaults + | +106 | def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}): + | ^^^^^^^^ B008 +107 | pass + | -B006_B008.py:96:60: B008 Do not perform function call `range` in argument defaults - | -96 | def set_comprehension_also_not_okay(default={i**2 for i in range(3)}): - | ^^^^^^^^ B008 -97 | pass - | +B006_B008.py:110:60: B008 Do not perform function call `range` in argument defaults + | +110 | def set_comprehension_also_not_okay(default={i**2 for i in range(3)}): + | ^^^^^^^^ B008 +111 | pass + | -B006_B008.py:112:39: B008 Do not perform function call `time.time` in argument defaults +B006_B008.py:126:39: B008 Do not perform function call `time.time` in argument defaults | -110 | # B008 -111 | # Flag function calls as default args (including if they are part of a sub-expression) -112 | def in_fact_all_calls_are_wrong(value=time.time()): +124 | # B008 +125 | # Flag function calls as default args (including if they are part of a sub-expression) +126 | def in_fact_all_calls_are_wrong(value=time.time()): | ^^^^^^^^^^^ B008 -113 | ... +127 | ... | -B006_B008.py:116:12: B008 Do not perform function call `dt.datetime.now` in argument defaults +B006_B008.py:130:12: B008 Do not perform function call `dt.datetime.now` in argument defaults | -116 | def f(when=dt.datetime.now() + dt.timedelta(days=7)): +130 | def f(when=dt.datetime.now() + dt.timedelta(days=7)): | ^^^^^^^^^^^^^^^^^ B008 -117 | pass +131 | pass | -B006_B008.py:120:30: B008 Do not perform function call in argument defaults +B006_B008.py:134:30: B008 Do not perform function call in argument defaults | -120 | def can_even_catch_lambdas(a=(lambda x: x)()): +134 | def can_even_catch_lambdas(a=(lambda x: x)()): | ^^^^^^^^^^^^^^^ B008 -121 | ... +135 | ... | -B006_B008.py:221:31: B008 Do not perform function call `dt.datetime.now` in argument defaults +B006_B008.py:239:31: B008 Do not perform function call `dt.datetime.now` in argument defaults | -219 | # B006 and B008 -220 | # We should handle arbitrary nesting of these B008. -221 | def nested_combo(a=[float(3), dt.datetime.now()]): +237 | # B006 and B008 +238 | # We should handle arbitrary nesting of these B008. +239 | def nested_combo(a=[float(3), dt.datetime.now()]): | ^^^^^^^^^^^^^^^^^ B008 -222 | pass +240 | pass | -B006_B008.py:227:22: B008 Do not perform function call `map` in argument defaults +B006_B008.py:245:22: B008 Do not perform function call `map` in argument defaults | -225 | # Don't flag nested B006 since we can't guarantee that -226 | # it isn't made mutable by the outer operation. -227 | def no_nested_b006(a=map(lambda s: s.upper(), ["a", "b", "c"])): +243 | # Don't flag nested B006 since we can't guarantee that +244 | # it isn't made mutable by the outer operation. +245 | def no_nested_b006(a=map(lambda s: s.upper(), ["a", "b", "c"])): | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B008 -228 | pass +246 | pass | -B006_B008.py:232:19: B008 Do not perform function call `random.randint` in argument defaults +B006_B008.py:250:19: B008 Do not perform function call `random.randint` in argument defaults | -231 | # B008-ception. -232 | def nested_b008(a=random.randint(0, dt.datetime.now().year)): +249 | # B008-ception. +250 | def nested_b008(a=random.randint(0, dt.datetime.now().year)): | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B008 -233 | pass +251 | pass | -B006_B008.py:232:37: B008 Do not perform function call `dt.datetime.now` in argument defaults +B006_B008.py:250:37: B008 Do not perform function call `dt.datetime.now` in argument defaults | -231 | # B008-ception. -232 | def nested_b008(a=random.randint(0, dt.datetime.now().year)): +249 | # B008-ception. +250 | def nested_b008(a=random.randint(0, dt.datetime.now().year)): | ^^^^^^^^^^^^^^^^^ B008 -233 | pass +251 | pass | diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B014_B014.py.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B014_B014.py.snap index bb8fb6c3c2001..52e3ea5167132 100644 --- a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B014_B014.py.snap +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B014_B014.py.snap @@ -64,4 +64,22 @@ B014.py:49:8: B014 [*] Exception handler with duplicate exception: `re.error` 51 51 | pass 52 52 | +B014.py:82:8: B014 [*] Exception handler with duplicate exception: `ValueError` + | +80 | try: +81 | pass +82 | except (ValueError, ValueError, TypeError): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B014 +83 | pass + | + = help: De-duplicate exceptions + +ℹ Fix +79 79 | # https://github.com/astral-sh/ruff/issues/6412 +80 80 | try: +81 81 | pass +82 |-except (ValueError, ValueError, TypeError): + 82 |+except (ValueError, TypeError): +83 83 | pass + diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B905_B905.py.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B905.py.snap similarity index 100% rename from crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B905_B905.py.snap rename to crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B905.py.snap diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_annotation.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_annotation.snap new file mode 100644 index 0000000000000..7bc5a28612e31 --- /dev/null +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_annotation.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/flake8_bugbear/mod.rs +--- +B006_extended.py:17:55: B006 [*] Do not use mutable data structures for argument defaults + | +17 | def error_due_to_missing_import(foo: ImmutableTypeA = []): + | ^^ B006 +18 | ... + | + = help: Replace with `None`; initialize within function + +ℹ Possible fix +14 14 | ... +15 15 | +16 16 | +17 |-def error_due_to_missing_import(foo: ImmutableTypeA = []): + 17 |+def error_due_to_missing_import(foo: ImmutableTypeA = None): + 18 |+ if foo is None: + 19 |+ foo = [] +18 20 | ... + + diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_default.snap similarity index 55% rename from crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls.snap rename to crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_default.snap index 8efe9b260c306..88a9b19016ba8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls.snap +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__extend_immutable_calls_arg_default.snap @@ -1,11 +1,11 @@ --- source: crates/ruff/src/rules/flake8_bugbear/mod.rs --- -B008_extended.py:19:51: B008 Do not perform function call `Depends` in argument defaults +B008_extended.py:24:51: B008 Do not perform function call `Depends` in argument defaults | -19 | def error_due_to_missing_import(data: List[str] = Depends(None)): +24 | def error_due_to_missing_import(data: List[str] = Depends(None)): | ^^^^^^^^^^^^^ B008 -20 | ... +25 | ... | diff --git a/crates/ruff/src/rules/flake8_builtins/rules/builtin_argument_shadowing.rs b/crates/ruff/src/rules/flake8_builtins/rules/builtin_argument_shadowing.rs index 064e5a48070e7..5f8418838bfb3 100644 --- a/crates/ruff/src/rules/flake8_builtins/rules/builtin_argument_shadowing.rs +++ b/crates/ruff/src/rules/flake8_builtins/rules/builtin_argument_shadowing.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arg, Ranged}; +use ruff_python_ast::{Parameter, Ranged}; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Violation; @@ -62,16 +62,16 @@ impl Violation for BuiltinArgumentShadowing { } /// A002 -pub(crate) fn builtin_argument_shadowing(checker: &mut Checker, argument: &Arg) { +pub(crate) fn builtin_argument_shadowing(checker: &mut Checker, parameter: &Parameter) { if shadows_builtin( - argument.arg.as_str(), + parameter.name.as_str(), &checker.settings.flake8_builtins.builtins_ignorelist, ) { checker.diagnostics.push(Diagnostic::new( BuiltinArgumentShadowing { - name: argument.arg.to_string(), + name: parameter.name.to_string(), }, - argument.range(), + parameter.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_builtins/rules/builtin_attribute_shadowing.rs b/crates/ruff/src/rules/flake8_builtins/rules/builtin_attribute_shadowing.rs index c89f261d26aff..f4069ff24b287 100644 --- a/crates/ruff/src/rules/flake8_builtins/rules/builtin_attribute_shadowing.rs +++ b/crates/ruff/src/rules/flake8_builtins/rules/builtin_attribute_shadowing.rs @@ -1,5 +1,5 @@ use ruff_python_ast as ast; -use ruff_python_ast::Decorator; +use ruff_python_ast::{Arguments, Decorator}; use ruff_text_size::TextRange; use ruff_diagnostics::Diagnostic; @@ -78,7 +78,7 @@ pub(crate) fn builtin_attribute_shadowing( // Ignore shadowing within `TypedDict` definitions, since these are only accessible through // subscripting and not through attribute access. if class_def - .bases + .bases() .iter() .any(|base| checker.semantic().match_typing_expr(base, "TypedDict")) { @@ -131,20 +131,23 @@ pub(crate) fn builtin_method_shadowing( fn is_standard_library_override( name: &str, class_def: &ast::StmtClassDef, - model: &SemanticModel, + semantic: &SemanticModel, ) -> bool { + let Some(Arguments { args: bases, .. }) = class_def.arguments.as_deref() else { + return false; + }; match name { // Ex) `Event#set` - "set" => class_def.bases.iter().any(|base| { - model.resolve_call_path(base).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["threading", "Event"]) - }) + "set" => bases.iter().any(|base| { + semantic + .resolve_call_path(base) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["threading", "Event"])) }), // Ex) `Filter#filter` - "filter" => class_def.bases.iter().any(|base| { - model.resolve_call_path(base).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["logging", "Filter"]) - }) + "filter" => bases.iter().any(|base| { + semantic + .resolve_call_path(base) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["logging", "Filter"])) }), _ => false, } diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index 785e3e9627545..8887808b5c09c 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -7,7 +7,7 @@ use libcst_native::{ RightParen, RightSquareBracket, Set, SetComp, SimpleString, SimpleWhitespace, TrailingWhitespace, Tuple, }; -use ruff_python_ast::Ranged; +use ruff_python_ast::{Expr, Ranged}; use ruff_text_size::TextRange; use ruff_diagnostics::{Edit, Fix}; @@ -28,7 +28,7 @@ use crate::{ pub(crate) fn fix_unnecessary_generator_list( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { // Expr(Call(GeneratorExp)))) -> Expr(ListComp))) let module_text = locator.slice(expr.range()); @@ -58,10 +58,7 @@ pub(crate) fn fix_unnecessary_generator_list( } /// (C401) Convert `set(x for x in y)` to `{x for x in y}`. -pub(crate) fn fix_unnecessary_generator_set( - checker: &Checker, - expr: &ruff_python_ast::Expr, -) -> Result { +pub(crate) fn fix_unnecessary_generator_set(checker: &Checker, expr: &Expr) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -96,10 +93,7 @@ pub(crate) fn fix_unnecessary_generator_set( /// (C402) Convert `dict((x, x) for x in range(3))` to `{x: x for x in /// range(3)}`. -pub(crate) fn fix_unnecessary_generator_dict( - checker: &Checker, - expr: &ruff_python_ast::Expr, -) -> Result { +pub(crate) fn fix_unnecessary_generator_dict(checker: &Checker, expr: &Expr) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -141,7 +135,7 @@ pub(crate) fn fix_unnecessary_generator_dict( /// (C403) Convert `set([x for x in y])` to `{x for x in y}`. pub(crate) fn fix_unnecessary_list_comprehension_set( checker: &Checker, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -177,7 +171,7 @@ pub(crate) fn fix_unnecessary_list_comprehension_set( /// range(3)}`. pub(crate) fn fix_unnecessary_list_comprehension_dict( checker: &Checker, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -262,10 +256,7 @@ fn drop_trailing_comma<'a>( } /// (C405) Convert `set((1, 2))` to `{1, 2}`. -pub(crate) fn fix_unnecessary_literal_set( - checker: &Checker, - expr: &ruff_python_ast::Expr, -) -> Result { +pub(crate) fn fix_unnecessary_literal_set(checker: &Checker, expr: &Expr) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -306,10 +297,7 @@ pub(crate) fn fix_unnecessary_literal_set( } /// (C406) Convert `dict([(1, 2)])` to `{1: 2}`. -pub(crate) fn fix_unnecessary_literal_dict( - checker: &Checker, - expr: &ruff_python_ast::Expr, -) -> Result { +pub(crate) fn fix_unnecessary_literal_dict(checker: &Checker, expr: &Expr) -> Result { let locator = checker.locator(); let stylist = checker.stylist(); @@ -372,10 +360,7 @@ pub(crate) fn fix_unnecessary_literal_dict( } /// (C408) -pub(crate) fn fix_unnecessary_collection_call( - checker: &Checker, - expr: &ruff_python_ast::Expr, -) -> Result { +pub(crate) fn fix_unnecessary_collection_call(checker: &Checker, expr: &Expr) -> Result { enum Collection { Tuple, List, @@ -535,7 +520,7 @@ fn pad_expression(content: String, range: TextRange, checker: &Checker) -> Strin pub(crate) fn fix_unnecessary_literal_within_tuple_call( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -585,7 +570,7 @@ pub(crate) fn fix_unnecessary_literal_within_tuple_call( pub(crate) fn fix_unnecessary_literal_within_list_call( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -637,7 +622,7 @@ pub(crate) fn fix_unnecessary_literal_within_list_call( pub(crate) fn fix_unnecessary_list_call( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { // Expr(Call(List|Tuple)))) -> Expr(List|Tuple))) let module_text = locator.slice(expr.range()); @@ -659,7 +644,7 @@ pub(crate) fn fix_unnecessary_list_call( pub(crate) fn fix_unnecessary_call_around_sorted( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -771,7 +756,7 @@ pub(crate) fn fix_unnecessary_call_around_sorted( pub(crate) fn fix_unnecessary_double_cast_or_process( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -780,13 +765,14 @@ pub(crate) fn fix_unnecessary_double_cast_or_process( outer_call.args = match outer_call.args.split_first() { Some((first, rest)) => { let inner_call = match_call(&first.value)?; - if let Some(iterable) = inner_call.args.first() { - let mut args = vec![iterable.clone()]; - args.extend_from_slice(rest); - args - } else { - bail!("Expected at least one argument in inner function call"); - } + inner_call + .args + .iter() + .filter(|argument| argument.keyword.is_none()) + .take(1) + .chain(rest.iter()) + .cloned() + .collect::>() } None => bail!("Expected at least one argument in outer function call"), }; @@ -801,7 +787,7 @@ pub(crate) fn fix_unnecessary_double_cast_or_process( pub(crate) fn fix_unnecessary_comprehension( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -888,8 +874,8 @@ pub(crate) fn fix_unnecessary_comprehension( pub(crate) fn fix_unnecessary_map( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, - parent: Option<&ruff_python_ast::Expr>, + expr: &Expr, + parent: Option<&Expr>, object_type: ObjectType, ) -> Result { let module_text = locator.slice(expr.range()); @@ -1018,7 +1004,7 @@ pub(crate) fn fix_unnecessary_map( // If the expression is embedded in an f-string, surround it with spaces to avoid // syntax errors. if matches!(object_type, ObjectType::Set | ObjectType::Dict) { - if parent.map_or(false, ruff_python_ast::Expr::is_formatted_value_expr) { + if parent.is_some_and(Expr::is_formatted_value_expr) { content = format!(" {content} "); } } @@ -1033,7 +1019,7 @@ pub(crate) fn fix_unnecessary_map( pub(crate) fn fix_unnecessary_literal_within_dict_call( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; @@ -1052,15 +1038,33 @@ pub(crate) fn fix_unnecessary_literal_within_dict_call( pub(crate) fn fix_unnecessary_comprehension_any_all( locator: &Locator, stylist: &Stylist, - expr: &ruff_python_ast::Expr, + expr: &Expr, ) -> Result { // Expr(ListComp) -> Expr(GeneratorExp) let module_text = locator.slice(expr.range()); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; - let Expression::ListComp(list_comp) = &call.args[0].value else { - bail!("Expected Expression::ListComp"); + let (whitespace_after, whitespace_before, elt, for_in, lpar, rpar) = match &call.args[0].value { + Expression::ListComp(list_comp) => ( + &list_comp.lbracket.whitespace_after, + &list_comp.rbracket.whitespace_before, + &list_comp.elt, + &list_comp.for_in, + &list_comp.lpar, + &list_comp.rpar, + ), + Expression::SetComp(set_comp) => ( + &set_comp.lbrace.whitespace_after, + &set_comp.rbrace.whitespace_before, + &set_comp.elt, + &set_comp.for_in, + &set_comp.lpar, + &set_comp.rpar, + ), + _ => { + bail!("Expected Expression::ListComp | Expression::SetComp"); + } }; let mut new_empty_lines = vec![]; @@ -1069,7 +1073,7 @@ pub(crate) fn fix_unnecessary_comprehension_any_all( first_line, empty_lines, .. - }) = &list_comp.lbracket.whitespace_after + }) = &whitespace_after { // If there's a comment on the line after the opening bracket, we need // to preserve it. The way we do this is by adding a new empty line @@ -1158,7 +1162,7 @@ pub(crate) fn fix_unnecessary_comprehension_any_all( .. }, .. - }) = &list_comp.rbracket.whitespace_before + }) = &whitespace_before { Some(format!("{}{}", whitespace.0, comment.0)) } else { @@ -1166,10 +1170,10 @@ pub(crate) fn fix_unnecessary_comprehension_any_all( }; call.args[0].value = Expression::GeneratorExp(Box::new(GeneratorExp { - elt: list_comp.elt.clone(), - for_in: list_comp.for_in.clone(), - lpar: list_comp.lpar.clone(), - rpar: list_comp.rpar.clone(), + elt: elt.clone(), + for_in: for_in.clone(), + lpar: lpar.clone(), + rpar: rpar.clone(), })); let whitespace_after_arg = match &call.args[0].comma { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs index af748a5f687f2..f22a8dd908509 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/helpers.rs @@ -1,12 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Keyword}; - -pub(super) fn expr_name(func: &Expr) -> Option<&str> { - if let Expr::Name(ast::ExprName { id, .. }) = func { - Some(id) - } else { - None - } -} +use ruff_python_ast::{Expr, Keyword}; pub(super) fn exactly_one_argument_with_matching_function<'a>( name: &str, @@ -20,7 +12,8 @@ pub(super) fn exactly_one_argument_with_matching_function<'a>( if !keywords.is_empty() { return None; } - if expr_name(func)? != name { + let func = func.as_name_expr()?; + if func.id != name { return None; } Some(arg) @@ -31,8 +24,8 @@ pub(super) fn first_argument_with_matching_function<'a>( func: &Expr, args: &'a [Expr], ) -> Option<&'a Expr> { - if expr_name(func)? == name { - Some(args.first()?) + if func.as_name_expr().is_some_and(|func| func.id == name) { + args.first() } else { None } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs index 6757c96aa359a..ae09498b2995d 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs @@ -1,14 +1,11 @@ -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::flake8_comprehensions::fixes; -use super::helpers; - /// ## What it does /// Checks for unnecessary `list` or `reversed` calls around `sorted` /// calls. @@ -57,10 +54,10 @@ pub(crate) fn unnecessary_call_around_sorted( func: &Expr, args: &[Expr], ) { - let Some(outer) = helpers::expr_name(func) else { + let Some(outer) = func.as_name_expr() else { return; }; - if !(outer == "list" || outer == "reversed") { + if !matches!(outer.id.as_str(), "list" | "reversed") { return; } let Some(arg) = args.first() else { @@ -69,18 +66,18 @@ pub(crate) fn unnecessary_call_around_sorted( let Expr::Call(ast::ExprCall { func, .. }) = arg else { return; }; - let Some(inner) = helpers::expr_name(func) else { + let Some(inner) = func.as_name_expr() else { return; }; - if inner != "sorted" { + if inner.id != "sorted" { return; } - if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) { + if !checker.semantic().is_builtin(&inner.id) || !checker.semantic().is_builtin(&outer.id) { return; } let mut diagnostic = Diagnostic::new( UnnecessaryCallAroundSorted { - func: outer.to_string(), + func: outer.id.to_string(), }, expr.range(), ); @@ -91,7 +88,7 @@ pub(crate) fn unnecessary_call_around_sorted( checker.stylist(), expr, )?; - if outer == "reversed" { + if outer.id == "reversed" { Ok(Fix::suggested(edit)) } else { Ok(Fix::automatic(edit)) diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs index 444a1856e1014..abae945c1929c 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs @@ -1,15 +1,12 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::flake8_comprehensions::fixes; use crate::rules::flake8_comprehensions::settings::Settings; -use super::helpers; - /// ## What it does /// Checks for unnecessary `dict`, `list` or `tuple` calls that can be /// rewritten as empty literals. @@ -63,10 +60,10 @@ pub(crate) fn unnecessary_collection_call( if !args.is_empty() { return; } - let Some(id) = helpers::expr_name(func) else { + let Some(func) = func.as_name_expr() else { return; }; - match id { + match func.id.as_str() { "dict" if keywords.is_empty() || (!settings.allow_dict_calls_with_keyword_arguments @@ -79,18 +76,19 @@ pub(crate) fn unnecessary_collection_call( } _ => return, }; - if !checker.semantic().is_builtin(id) { + if !checker.semantic().is_builtin(func.id.as_str()) { return; } let mut diagnostic = Diagnostic::new( UnnecessaryCollectionCall { - obj_type: id.to_string(), + obj_type: func.id.to_string(), }, expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| fixes::fix_unnecessary_collection_call(checker, expr)); + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_collection_call(checker, expr).map(Fix::suggested) + }); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs index c9a7887dabfd1..9fe91e5ee71fa 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs @@ -1,14 +1,11 @@ -use ruff_python_ast::{self as ast, Comprehension, Expr, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Comprehension, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::flake8_comprehensions::fixes; -use super::helpers; - /// ## What it does /// Checks for unnecessary `dict`, `list`, and `set` comprehension. /// @@ -66,9 +63,9 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) { expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_comprehension(checker.locator(), checker.stylist(), expr) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); @@ -88,28 +85,28 @@ pub(crate) fn unnecessary_dict_comprehension( if !generator.ifs.is_empty() || generator.is_async { return; } - let Some(key_id) = helpers::expr_name(key) else { + let Some(key) = key.as_name_expr() else { return; }; - let Some(value_id) = helpers::expr_name(value) else { + let Some(value) = value.as_name_expr() else { return; }; let Expr::Tuple(ast::ExprTuple { elts, .. }) = &generator.target else { return; }; - if elts.len() != 2 { - return; - } - let Some(target_key_id) = helpers::expr_name(&elts[0]) else { + let [target_key, target_value] = elts.as_slice() else { return; }; - if target_key_id != key_id { + let Some(target_key) = target_key.as_name_expr() else { return; - } - let Some(target_value_id) = helpers::expr_name(&elts[1]) else { + }; + let Some(target_value) = target_value.as_name_expr() else { return; }; - if target_value_id != value_id { + if target_key.id != key.id { + return; + } + if target_value.id != value.id { return; } add_diagnostic(checker, expr); @@ -128,13 +125,13 @@ pub(crate) fn unnecessary_list_set_comprehension( if !generator.ifs.is_empty() || generator.is_async { return; } - let Some(elt_id) = helpers::expr_name(elt) else { + let Some(elt) = elt.as_name_expr() else { return; }; - let Some(target_id) = helpers::expr_name(&generator.target) else { + let Some(target) = generator.target.as_name_expr() else { return; }; - if elt_id != target_id { + if elt.id != target.id { return; } add_diagnostic(checker, expr); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs index b59f68a1c5cce..00cdcfea4d55b 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs @@ -69,30 +69,31 @@ pub(crate) fn unnecessary_comprehension_any_all( let Expr::Name(ast::ExprName { id, .. }) = func else { return; }; - if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 { - let (Expr::ListComp(ast::ExprListComp { elt, .. }) - | Expr::SetComp(ast::ExprSetComp { elt, .. })) = &args[0] - else { - return; - }; - if contains_await(elt) { - return; - } - if !checker.semantic().is_builtin(id) { - return; - } - let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, args[0].range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_comprehension_any_all( - checker.locator(), - checker.stylist(), - expr, - ) - }); - } - checker.diagnostics.push(diagnostic); + if !matches!(id.as_str(), "all" | "any") { + return; + } + let [arg] = args else { + return; + }; + let (Expr::ListComp(ast::ExprListComp { elt, .. }) + | Expr::SetComp(ast::ExprSetComp { elt, .. })) = arg + else { + return; + }; + if contains_await(elt) { + return; + } + if !checker.semantic().is_builtin(id) { + return; + } + + let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, arg.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_comprehension_any_all(checker.locator(), checker.stylist(), expr) + }); } + checker.diagnostics.push(diagnostic); } /// Return `true` if the [`Expr`] contains an `await` expression. diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs index 8f399460bec5a..cdf893625d618 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs @@ -1,15 +1,12 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableKeyword; +use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::flake8_comprehensions::fixes; -use super::helpers; - /// ## What it does /// Checks for unnecessary `list`, `reversed`, `set`, `sorted`, and `tuple` /// call within `list`, `set`, `sorted`, and `tuple` calls. @@ -72,15 +69,13 @@ pub(crate) fn unnecessary_double_cast_or_process( args: &[Expr], outer_kw: &[Keyword], ) { - let Some(outer) = helpers::expr_name(func) else { + let Some(outer) = func.as_name_expr() else { return; }; - if !(outer == "list" - || outer == "tuple" - || outer == "set" - || outer == "reversed" - || outer == "sorted") - { + if !matches!( + outer.id.as_str(), + "list" | "tuple" | "set" | "reversed" | "sorted" + ) { return; } let Some(arg) = args.first() else { @@ -88,22 +83,24 @@ pub(crate) fn unnecessary_double_cast_or_process( }; let Expr::Call(ast::ExprCall { func, - keywords: inner_kw, + arguments: Arguments { + keywords: inner_kw, .. + }, .. }) = arg else { return; }; - let Some(inner) = helpers::expr_name(func) else { + let Some(inner) = func.as_name_expr() else { return; }; - if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) { + if !checker.semantic().is_builtin(&inner.id) || !checker.semantic().is_builtin(&outer.id) { return; } // Avoid collapsing nested `sorted` calls with non-identical keyword arguments // (i.e., `key`, `reverse`). - if inner == "sorted" && outer == "sorted" { + if inner.id == "sorted" && outer.id == "sorted" { if inner_kw.len() != outer_kw.len() { return; } @@ -116,29 +113,30 @@ pub(crate) fn unnecessary_double_cast_or_process( } } - // Ex) set(tuple(...)) - // Ex) list(tuple(...)) - // Ex) set(set(...)) - if ((outer == "set" || outer == "sorted") - && (inner == "list" || inner == "tuple" || inner == "reversed" || inner == "sorted")) - || (outer == "set" && inner == "set") - || ((outer == "list" || outer == "tuple") && (inner == "list" || inner == "tuple")) - { + // Ex) `set(tuple(...))` + // Ex) `list(tuple(...))` + // Ex) `set(set(...))` + if matches!( + (outer.id.as_str(), inner.id.as_str()), + ("set" | "sorted", "list" | "tuple" | "reversed" | "sorted") + | ("set", "set") + | ("list" | "tuple", "list" | "tuple") + ) { let mut diagnostic = Diagnostic::new( UnnecessaryDoubleCastOrProcess { - inner: inner.to_string(), - outer: outer.to_string(), + inner: inner.id.to_string(), + outer: outer.id.to_string(), }, expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_double_cast_or_process( checker.locator(), checker.stylist(), expr, ) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs index 3695edfa8b4b2..26e1fe42a25d5 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -59,9 +58,8 @@ pub(crate) fn unnecessary_generator_dict( Expr::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2 => { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { - fixes::fix_unnecessary_generator_dict(checker, expr) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_generator_dict(checker, expr).map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs index 53fa7f9cd3291..8f46043c17577 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -60,9 +60,9 @@ pub(crate) fn unnecessary_generator_list( if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_generator_list(checker.locator(), checker.stylist(), expr) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs index 93b1c0a2c2bed..e89399719beb3 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -60,9 +60,9 @@ pub(crate) fn unnecessary_generator_set( if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic - .try_set_fix_from_edit(|| fixes::fix_unnecessary_generator_set(checker, expr)); + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_generator_set(checker, expr).map(Fix::suggested) + }); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs index ab23652ea7664..18f980291ecfe 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -56,9 +56,9 @@ pub(crate) fn unnecessary_list_call( } let mut diagnostic = Diagnostic::new(UnnecessaryListCall, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_list_call(checker.locator(), checker.stylist(), expr) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs index 9bc396a340959..2cc597ae60eda 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -66,9 +65,8 @@ pub(crate) fn unnecessary_list_comprehension_dict( } let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionDict, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { - fixes::fix_unnecessary_list_comprehension_dict(checker, expr) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_list_comprehension_dict(checker, expr).map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs index 7f30732a6c19a..20d45cdf1ad9d 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -58,9 +58,8 @@ pub(crate) fn unnecessary_list_comprehension_set( if argument.is_list_comp_expr() { let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionSet, expr.range()); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { - fixes::fix_unnecessary_list_comprehension_set(checker, expr) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_list_comprehension_set(checker, expr).map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs index 31a30a762482a..d1b098962c52c 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -70,7 +69,7 @@ pub(crate) fn unnecessary_literal_dict( // Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`. if !elts .iter() - .all(|elt| matches!(&elt, Expr::Tuple(ast::ExprTuple { elts, .. } )if elts.len() == 2)) + .all(|elt| matches!(&elt, Expr::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2)) { return; } @@ -81,8 +80,8 @@ pub(crate) fn unnecessary_literal_dict( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| fixes::fix_unnecessary_literal_dict(checker, expr)); + diagnostic + .try_set_fix(|| fixes::fix_unnecessary_literal_dict(checker, expr).map(Fix::suggested)); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs index 31fbe2c27ff43..ccf78fb94ad88 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -75,8 +75,8 @@ pub(crate) fn unnecessary_literal_set( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| fixes::fix_unnecessary_literal_set(checker, expr)); + diagnostic + .try_set_fix(|| fixes::fix_unnecessary_literal_set(checker, expr).map(Fix::suggested)); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs index cd9a1f8005d92..c43259f52816f 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs @@ -2,7 +2,7 @@ use std::fmt; use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -91,13 +91,13 @@ pub(crate) fn unnecessary_literal_within_dict_call( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_literal_within_dict_call( checker.locator(), checker.stylist(), expr, ) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs index bfda74657a757..8d625d6115893 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Expr, Keyword, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -94,13 +93,13 @@ pub(crate) fn unnecessary_literal_within_list_call( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_literal_within_list_call( checker.locator(), checker.stylist(), expr, ) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs index 8d04c8cb22dcc..10bc9dd19f6d8 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs @@ -1,6 +1,6 @@ use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -95,13 +95,13 @@ pub(crate) fn unnecessary_literal_within_tuple_call( expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fixes::fix_unnecessary_literal_within_tuple_call( checker.locator(), checker.stylist(), expr, ) + .map(Fix::suggested) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs index d6a6e6b9e4f4a..11c0d1a6094b7 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs @@ -1,13 +1,11 @@ use std::fmt; -use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Ranged, Stmt}; - use ruff_diagnostics::{AutofixKind, Violation}; use ruff_diagnostics::{Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::includes_arg_name; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Parameters, Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -70,11 +68,11 @@ pub(crate) fn unnecessary_map( func: &Expr, args: &[Expr], ) { - let Some(id) = helpers::expr_name(func) else { + let Some(func) = func.as_name_expr() else { return; }; - let object_type = match id { + let object_type = match func.id.as_str() { "map" => ObjectType::Generator, "list" => ObjectType::List, "set" => ObjectType::Set, @@ -82,33 +80,51 @@ pub(crate) fn unnecessary_map( _ => return, }; - if !checker.semantic().is_builtin(id) { + if !checker.semantic().is_builtin(&func.id) { return; } match object_type { ObjectType::Generator => { // Exclude the parent if already matched by other arms. - if let Some(Expr::Call(ast::ExprCall { func, .. })) = parent { - if let Some(name) = helpers::expr_name(func) { - if matches!(name, "list" | "set" | "dict") { - return; - } - } - }; + if parent + .and_then(ruff_python_ast::Expr::as_call_expr) + .and_then(|call| call.func.as_name_expr()) + .is_some_and(|name| matches!(name.id.as_str(), "list" | "set" | "dict")) + { + return; + } // Only flag, e.g., `map(lambda x: x + 1, iterable)`. - let [Expr::Lambda(ast::ExprLambda { args, body, .. }), _] = args else { + let [Expr::Lambda(ast::ExprLambda { + parameters, body, .. + }), _] = args + else { return; }; - if late_binding(args, body) { + if parameters.as_ref().is_some_and(|parameters| { + late_binding(parameters, body) + || parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .any(|param| param.default.is_some()) + || parameters.vararg.is_some() + || parameters.kwarg.is_some() + }) { return; } } ObjectType::List | ObjectType::Set => { // Only flag, e.g., `list(map(lambda x: x + 1, iterable))`. - let [Expr::Call(ast::ExprCall { func, args, .. })] = args else { + let [Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + })] = args + else { return; }; @@ -121,17 +137,35 @@ pub(crate) fn unnecessary_map( return; }; - let Expr::Lambda(ast::ExprLambda { args, body, .. }) = argument else { + let Expr::Lambda(ast::ExprLambda { + parameters, body, .. + }) = argument + else { return; }; - if late_binding(args, body) { + if parameters.as_ref().is_some_and(|parameters| { + late_binding(parameters, body) + || parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .any(|param| param.default.is_some()) + || parameters.vararg.is_some() + || parameters.kwarg.is_some() + }) { return; } } ObjectType::Dict => { // Only flag, e.g., `dict(map(lambda v: (v, v ** 2), values))`. - let [Expr::Call(ast::ExprCall { func, args, .. })] = args else { + let [Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + })] = args + else { return; }; @@ -140,7 +174,10 @@ pub(crate) fn unnecessary_map( return; }; - let Expr::Lambda(ast::ExprLambda { args, body, .. }) = argument else { + let Expr::Lambda(ast::ExprLambda { + parameters, body, .. + }) = argument + else { return; }; @@ -154,11 +191,21 @@ pub(crate) fn unnecessary_map( return; } - if late_binding(args, body) { + if parameters.as_ref().is_some_and(|parameters| { + late_binding(parameters, body) + || parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .any(|param| param.default.is_some()) + || parameters.vararg.is_some() + || parameters.kwarg.is_some() + }) { return; } } - } + }; let mut diagnostic = Diagnostic::new(UnnecessaryMap { object_type }, expr.range()); if checker.patch(diagnostic.kind.rule()) { @@ -195,7 +242,7 @@ impl fmt::Display for ObjectType { } } -/// Returns `true` if the lambda defined by the given arguments and body contains any names that +/// Returns `true` if the lambda defined by the given parameters and body contains any names that /// are late-bound within nested lambdas. /// /// For example, given: @@ -212,8 +259,8 @@ impl fmt::Display for ObjectType { /// /// Would yield an incorrect result, as the `x` in the inner lambda would be bound to the last /// value of `x` in the comprehension. -fn late_binding(args: &Arguments, body: &Expr) -> bool { - let mut visitor = LateBindingVisitor::new(args); +fn late_binding(parameters: &Parameters, body: &Expr) -> bool { + let mut visitor = LateBindingVisitor::new(parameters); visitor.visit_expr(body); visitor.late_bound } @@ -221,17 +268,17 @@ fn late_binding(args: &Arguments, body: &Expr) -> bool { #[derive(Debug)] struct LateBindingVisitor<'a> { /// The arguments to the current lambda. - args: &'a Arguments, + parameters: &'a Parameters, /// The arguments to any lambdas within the current lambda body. - lambdas: Vec<&'a Arguments>, + lambdas: Vec>, /// Whether any names within the current lambda body are late-bound within nested lambdas. late_bound: bool, } impl<'a> LateBindingVisitor<'a> { - fn new(args: &'a Arguments) -> Self { + fn new(parameters: &'a Parameters) -> Self { Self { - args, + parameters, lambdas: Vec::new(), late_bound: false, } @@ -243,8 +290,8 @@ impl<'a> Visitor<'a> for LateBindingVisitor<'a> { fn visit_expr(&mut self, expr: &'a Expr) { match expr { - Expr::Lambda(ast::ExprLambda { args, .. }) => { - self.lambdas.push(args); + Expr::Lambda(ast::ExprLambda { parameters, .. }) => { + self.lambdas.push(parameters.as_deref()); visitor::walk_expr(self, expr); self.lambdas.pop(); } @@ -256,9 +303,13 @@ impl<'a> Visitor<'a> for LateBindingVisitor<'a> { // If we're within a nested lambda... if !self.lambdas.is_empty() { // If the name is defined in the current lambda... - if includes_arg_name(id, self.args) { + if self.parameters.includes(id) { // And isn't overridden by any nested lambdas... - if !self.lambdas.iter().any(|args| includes_arg_name(id, args)) { + if !self.lambdas.iter().any(|parameters| { + parameters + .as_ref() + .is_some_and(|parameters| parameters.includes(id)) + }) { // Then it's late-bound. self.late_bound = true; } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs index 60076232c4306..092713ab4ec42 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs @@ -1,13 +1,11 @@ use num_bigint::BigInt; -use ruff_python_ast::{self as ast, Constant, Expr, Ranged, UnaryOp}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged, UnaryOp}; use crate::checkers::ast::Checker; -use super::helpers; - /// ## What it does /// Checks for unnecessary subscript reversal of iterable. /// @@ -52,13 +50,13 @@ pub(crate) fn unnecessary_subscript_reversal( let Some(first_arg) = args.first() else { return; }; - let Some(id) = helpers::expr_name(func) else { + let Some(func) = func.as_name_expr() else { return; }; - if !(id == "set" || id == "sorted" || id == "reversed") { + if !matches!(func.id.as_str(), "reversed" | "set" | "sorted") { return; } - if !checker.semantic().is_builtin(id) { + if !checker.semantic().is_builtin(&func.id) { return; } let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else { @@ -99,7 +97,7 @@ pub(crate) fn unnecessary_subscript_reversal( }; checker.diagnostics.push(Diagnostic::new( UnnecessarySubscriptReversal { - func: id.to_string(), + func: func.id.to_string(), }, expr.range(), )); diff --git a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C414_C414.py.snap b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C414_C414.py.snap index fb2d7cefc930f..2aabf2b2f96c4 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C414_C414.py.snap +++ b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C414_C414.py.snap @@ -365,8 +365,8 @@ C414.py:19:1: C414 [*] Unnecessary `list` call within `tuple()` 23 | | ) 24 | | ) | |_^ C414 -25 | -26 | # Nested sorts with differing keyword arguments. Not flagged. +25 | set(set()) +26 | set(list()) | = help: Remove the inner `list` call @@ -380,8 +380,91 @@ C414.py:19:1: C414 [*] Unnecessary `list` call within `tuple()` 22 21 | "o"] 23 22 | ) 24 |-) -25 23 | -26 24 | # Nested sorts with differing keyword arguments. Not flagged. -27 25 | sorted(sorted(x, key=lambda y: y)) +25 23 | set(set()) +26 24 | set(list()) +27 25 | set(tuple()) + +C414.py:25:1: C414 [*] Unnecessary `set` call within `set()` + | +23 | ) +24 | ) +25 | set(set()) + | ^^^^^^^^^^ C414 +26 | set(list()) +27 | set(tuple()) + | + = help: Remove the inner `set` call + +ℹ Suggested fix +22 22 | "o"] +23 23 | ) +24 24 | ) +25 |-set(set()) + 25 |+set() +26 26 | set(list()) +27 27 | set(tuple()) +28 28 | sorted(reversed()) + +C414.py:26:1: C414 [*] Unnecessary `list` call within `set()` + | +24 | ) +25 | set(set()) +26 | set(list()) + | ^^^^^^^^^^^ C414 +27 | set(tuple()) +28 | sorted(reversed()) + | + = help: Remove the inner `list` call + +ℹ Suggested fix +23 23 | ) +24 24 | ) +25 25 | set(set()) +26 |-set(list()) + 26 |+set() +27 27 | set(tuple()) +28 28 | sorted(reversed()) +29 29 | + +C414.py:27:1: C414 [*] Unnecessary `tuple` call within `set()` + | +25 | set(set()) +26 | set(list()) +27 | set(tuple()) + | ^^^^^^^^^^^^ C414 +28 | sorted(reversed()) + | + = help: Remove the inner `tuple` call + +ℹ Suggested fix +24 24 | ) +25 25 | set(set()) +26 26 | set(list()) +27 |-set(tuple()) + 27 |+set() +28 28 | sorted(reversed()) +29 29 | +30 30 | # Nested sorts with differing keyword arguments. Not flagged. + +C414.py:28:1: C414 [*] Unnecessary `reversed` call within `sorted()` + | +26 | set(list()) +27 | set(tuple()) +28 | sorted(reversed()) + | ^^^^^^^^^^^^^^^^^^ C414 +29 | +30 | # Nested sorts with differing keyword arguments. Not flagged. + | + = help: Remove the inner `reversed` call + +ℹ Suggested fix +25 25 | set(set()) +26 26 | set(list()) +27 27 | set(tuple()) +28 |-sorted(reversed()) + 28 |+sorted() +29 29 | +30 30 | # Nested sorts with differing keyword arguments. Not flagged. +31 31 | sorted(sorted(x, key=lambda y: y)) diff --git a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C417_C417.py.snap b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C417_C417.py.snap index acb6700d3fbed..c04bcb03b9fd8 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C417_C417.py.snap +++ b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C417_C417.py.snap @@ -226,7 +226,7 @@ C417.py:15:8: C417 [*] Unnecessary `map` usage (rewrite using a `set` comprehens 15 |+_ = f"{ {x % 2 == 0 for x in nums} }" 16 16 | _ = f"{dict(map(lambda v: (v, v**2), nums))}" 17 17 | -18 18 | # Error, but unfixable. +18 18 | # False negatives. C417.py:16:8: C417 [*] Unnecessary `map` usage (rewrite using a `dict` comprehension) | @@ -235,7 +235,7 @@ C417.py:16:8: C417 [*] Unnecessary `map` usage (rewrite using a `dict` comprehen 16 | _ = f"{dict(map(lambda v: (v, v**2), nums))}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C417 17 | -18 | # Error, but unfixable. +18 | # False negatives. | = help: Replace `map` with a `dict` comprehension @@ -246,33 +246,27 @@ C417.py:16:8: C417 [*] Unnecessary `map` usage (rewrite using a `dict` comprehen 16 |-_ = f"{dict(map(lambda v: (v, v**2), nums))}" 16 |+_ = f"{ {v: v**2 for v in nums} }" 17 17 | -18 18 | # Error, but unfixable. -19 19 | # For simple expressions, this could be: `(x if x else 1 for x in nums)`. +18 18 | # False negatives. +19 19 | map(lambda x=2, y=1: x + y, nums, nums) -C417.py:21:1: C417 Unnecessary `map` usage (rewrite using a generator expression) +C417.py:34:1: C417 [*] Unnecessary `map` usage (rewrite using a generator expression) | -19 | # For simple expressions, this could be: `(x if x else 1 for x in nums)`. -20 | # For more complex expressions, this would differ: `(x + 2 if x else 3 for x in nums)`. -21 | map(lambda x=1: x, nums) - | ^^^^^^^^^^^^^^^^^^^^^^^^ C417 -22 | -23 | # False negatives. - | - = help: Replace `map` with a generator expression - -C417.py:39:1: C417 [*] Unnecessary `map` usage (rewrite using a generator expression) - | -38 | # Error: the `x` is overridden by the inner lambda. -39 | map(lambda x: lambda x: x, range(4)) +33 | # Error: the `x` is overridden by the inner lambda. +34 | map(lambda x: lambda x: x, range(4)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C417 +35 | +36 | # Ok because of the default parameters, and variadic arguments. | = help: Replace `map` with a generator expression ℹ Suggested fix -36 36 | map(lambda x: lambda: x, range(4)) -37 37 | -38 38 | # Error: the `x` is overridden by the inner lambda. -39 |-map(lambda x: lambda x: x, range(4)) - 39 |+(lambda x: x for x in range(4)) +31 31 | map(lambda x: lambda: x, range(4)) +32 32 | +33 33 | # Error: the `x` is overridden by the inner lambda. +34 |-map(lambda x: lambda x: x, range(4)) + 34 |+(lambda x: x for x in range(4)) +35 35 | +36 36 | # Ok because of the default parameters, and variadic arguments. +37 37 | map(lambda x=1: x, nums) diff --git a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C419_C419.py.snap b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C419_C419.py.snap index 801ab960f4b28..c0546111c4095 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C419_C419.py.snap +++ b/crates/ruff/src/rules/flake8_comprehensions/snapshots/ruff__rules__flake8_comprehensions__tests__C419_C419.py.snap @@ -77,7 +77,7 @@ C419.py:7:5: C419 [*] Unnecessary list comprehension. 9 9 | any({x.id for x in bar}) 10 10 | -C419.py:9:5: C419 Unnecessary list comprehension. +C419.py:9:5: C419 [*] Unnecessary list comprehension. | 7 | [x.id for x in bar], # second comment 8 | ) # third comment @@ -88,6 +88,16 @@ C419.py:9:5: C419 Unnecessary list comprehension. | = help: Remove unnecessary list comprehension +ℹ Suggested fix +6 6 | all( # first comment +7 7 | [x.id for x in bar], # second comment +8 8 | ) # third comment +9 |-any({x.id for x in bar}) + 9 |+any(x.id for x in bar) +10 10 | +11 11 | # OK +12 12 | all(x.id for x in bar) + C419.py:24:5: C419 [*] Unnecessary list comprehension. | 22 | # Special comment handling diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_date_fromtimestamp.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_date_fromtimestamp.rs index 1d439d6e67ce7..ef4e46811a1fe 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_date_fromtimestamp.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_date_fromtimestamp.rs @@ -6,6 +6,43 @@ use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; +/// ## What it does +/// Checks for usage of `datetime.date.fromtimestamp()`. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.date.fromtimestamp(ts)` returns a naive datetime object. +/// Instead, use `datetime.datetime.fromtimestamp(ts, tz=)` to return a +/// timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.date.fromtimestamp(946684800) +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.UTC) +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDateFromtimestamp; @@ -19,17 +56,11 @@ impl Violation for CallDateFromtimestamp { } } -/// Checks for `datetime.date.fromtimestamp()`. (DTZ012) -/// -/// ## Why is this bad? -/// -/// It uses the system local timezone. -/// Use `datetime.datetime.fromtimestamp(, tz=).date()` instead. pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["datetime", "date", "fromtimestamp"]) }) { diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_date_today.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_date_today.rs index 9dfbfeed166a6..17b55a14d546f 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_date_today.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_date_today.rs @@ -6,6 +6,42 @@ use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; +/// ## What it does +/// Checks for usage of `datetime.date.today()`. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.date.today` returns a naive datetime object. Instead, use +/// `datetime.datetime.now(tz=).date()` to return a timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.today() +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.timezone.utc).date() +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.UTC).date() +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDateToday; @@ -19,19 +55,11 @@ impl Violation for CallDateToday { } } -/// Checks for `datetime.date.today()`. (DTZ011) -/// -/// ## Why is this bad? -/// -/// It uses the system local timezone. -/// Use `datetime.datetime.now(tz=).date()` instead. pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "date", "today"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "date", "today"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_fromtimestamp.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_fromtimestamp.rs index c65654e368d5f..25c86ae1ecb62 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_fromtimestamp.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_fromtimestamp.rs @@ -1,14 +1,51 @@ -use ruff_python_ast::{Expr, Keyword}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{has_non_none_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; +use crate::rules::flake8_datetimez::rules::helpers::has_non_none_keyword; use super::helpers; +/// ## What it does +/// Checks for usage of `datetime.datetime.fromtimestamp()` without a `tz` +/// argument. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.datetime.fromtimestamp(ts)` returns a naive datetime object. +/// Instead, use `datetime.datetime.fromtimestamp(ts, tz=)` to return a +/// timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800) +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.UTC) +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDatetimeFromtimestamp; @@ -21,18 +58,11 @@ impl Violation for CallDatetimeFromtimestamp { } } -/// DTZ006 -pub(crate) fn call_datetime_fromtimestamp( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], - location: TextRange, -) { +pub(crate) fn call_datetime_fromtimestamp(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { + .resolve_call_path(&call.func) + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["datetime", "datetime", "fromtimestamp"] @@ -47,25 +77,25 @@ pub(crate) fn call_datetime_fromtimestamp( } // no args / no args unqualified - if args.len() < 2 && keywords.is_empty() { + if call.arguments.args.len() < 2 && call.arguments.keywords.is_empty() { checker .diagnostics - .push(Diagnostic::new(CallDatetimeFromtimestamp, location)); + .push(Diagnostic::new(CallDatetimeFromtimestamp, call.range())); return; } // none args - if args.len() > 1 && is_const_none(&args[1]) { + if call.arguments.args.len() > 1 && is_const_none(&call.arguments.args[1]) { checker .diagnostics - .push(Diagnostic::new(CallDatetimeFromtimestamp, location)); + .push(Diagnostic::new(CallDatetimeFromtimestamp, call.range())); return; } // wrong keywords / none keyword - if !keywords.is_empty() && !has_non_none_keyword(keywords, "tz") { + if !call.arguments.keywords.is_empty() && !has_non_none_keyword(&call.arguments, "tz") { checker .diagnostics - .push(Diagnostic::new(CallDatetimeFromtimestamp, location)); + .push(Diagnostic::new(CallDatetimeFromtimestamp, call.range())); } } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_now_without_tzinfo.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_now_without_tzinfo.rs index 18b34fe553155..73dd721684817 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_now_without_tzinfo.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_now_without_tzinfo.rs @@ -1,14 +1,49 @@ -use ruff_python_ast::{Expr, Keyword}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{has_non_none_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; +use crate::rules::flake8_datetimez::rules::helpers::has_non_none_keyword; use super::helpers; +/// ## What it does +/// Checks for usage of `datetime.datetime.now()` without a `tz` argument. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.datetime.now()` returns a naive datetime object. Instead, use +/// `datetime.datetime.now(tz=)` to return a timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.now() +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.UTC) +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDatetimeNowWithoutTzinfo; @@ -19,20 +54,11 @@ impl Violation for CallDatetimeNowWithoutTzinfo { } } -/// DTZ005 -pub(crate) fn call_datetime_now_without_tzinfo( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], - location: TextRange, -) { +pub(crate) fn call_datetime_now_without_tzinfo(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "datetime", "now"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "datetime", "now"])) { return; } @@ -42,25 +68,25 @@ pub(crate) fn call_datetime_now_without_tzinfo( } // no args / no args unqualified - if args.is_empty() && keywords.is_empty() { + if call.arguments.args.is_empty() && call.arguments.keywords.is_empty() { checker .diagnostics - .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, location)); + .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, call.range())); return; } // none args - if !args.is_empty() && is_const_none(&args[0]) { + if call.arguments.args.first().is_some_and(is_const_none) { checker .diagnostics - .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, location)); + .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, call.range())); return; } // wrong keywords / none keyword - if !keywords.is_empty() && !has_non_none_keyword(keywords, "tz") { + if !call.arguments.keywords.is_empty() && !has_non_none_keyword(&call.arguments, "tz") { checker .diagnostics - .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, location)); + .push(Diagnostic::new(CallDatetimeNowWithoutTzinfo, call.range())); } } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_strptime_without_zone.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_strptime_without_zone.rs index d8f428d3c6d71..c516f9c3ab9d2 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_strptime_without_zone.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_strptime_without_zone.rs @@ -1,12 +1,53 @@ -use ruff_python_ast::{self as ast, Constant, Expr}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::has_non_none_keyword; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; +use crate::rules::flake8_datetimez::rules::helpers::has_non_none_keyword; +/// ## What it does +/// Checks for uses of `datetime.datetime.strptime()` that lead to naive +/// datetime objects. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.datetime.strptime()` without `%z` returns a naive datetime +/// object. Follow it with `.replace(tzinfo=)` or `.astimezone()`. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.strptime("2022/01/31", "%Y/%m/%d") +/// ``` +/// +/// Instead, use `.replace(tzinfo=)`: +/// ```python +/// import datetime +/// +/// datetime.datetime.strptime("2022/01/31", "%Y/%m/%d").replace( +/// tzinfo=datetime.timezone.utc +/// ) +/// ``` +/// +/// Or, use `.astimezone()`: +/// ```python +/// import datetime +/// +/// datetime.datetime.strptime("2022/01/31", "%Y/%m/%d").astimezone(datetime.timezone.utc) +/// ``` +/// +/// On Python 3.11 and later, `datetime.timezone.utc` can be replaced with +/// `datetime.UTC`. +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) +/// - [Python documentation: `strftime()` and `strptime()` Behavior](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) #[violation] pub struct CallDatetimeStrptimeWithoutZone; @@ -21,16 +62,11 @@ impl Violation for CallDatetimeStrptimeWithoutZone { } /// DTZ007 -pub(crate) fn call_datetime_strptime_without_zone( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - location: TextRange, -) { +pub(crate) fn call_datetime_strptime_without_zone(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { + .resolve_call_path(&call.func) + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["datetime", "datetime", "strptime"]) }) { @@ -42,7 +78,7 @@ pub(crate) fn call_datetime_strptime_without_zone( value: Constant::Str(format), kind: None, range: _, - })) = args.get(1).as_ref() + })) = call.arguments.args.get(1).as_ref() { if format.contains("%z") { return; @@ -50,16 +86,17 @@ pub(crate) fn call_datetime_strptime_without_zone( }; let (Some(grandparent), Some(parent)) = ( - checker.semantic().expr_grandparent(), - checker.semantic().expr_parent(), + checker.semantic().current_expression_grandparent(), + checker.semantic().current_expression_parent(), ) else { - checker - .diagnostics - .push(Diagnostic::new(CallDatetimeStrptimeWithoutZone, location)); + checker.diagnostics.push(Diagnostic::new( + CallDatetimeStrptimeWithoutZone, + call.range(), + )); return; }; - if let Expr::Call(ast::ExprCall { keywords, .. }) = grandparent { + if let Expr::Call(ast::ExprCall { arguments, .. }) = grandparent { if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = parent { let attr = attr.as_str(); // Ex) `datetime.strptime(...).astimezone()` @@ -69,14 +106,15 @@ pub(crate) fn call_datetime_strptime_without_zone( // Ex) `datetime.strptime(...).replace(tzinfo=UTC)` if attr == "replace" { - if has_non_none_keyword(keywords, "tzinfo") { + if has_non_none_keyword(arguments, "tzinfo") { return; } } } } - checker - .diagnostics - .push(Diagnostic::new(CallDatetimeStrptimeWithoutZone, location)); + checker.diagnostics.push(Diagnostic::new( + CallDatetimeStrptimeWithoutZone, + call.range(), + )); } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_today.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_today.rs index 0528f510cec7a..d1b89c794d0de 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_today.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_today.rs @@ -18,9 +18,8 @@ use super::helpers; /// `datetime` objects are preferred, as they represent a specific moment in /// time, unlike "naive" objects. /// -/// `datetime.datetime.today()` crates a "naive" object; instead, use -/// instead, use `datetime.datetime.now(tz=)` to create a timezone-aware -/// object. +/// `datetime.datetime.today()` creates a "naive" object; instead, use +/// `datetime.datetime.now(tz=)` to create a timezone-aware object. /// /// ## Example /// ```python @@ -59,9 +58,7 @@ pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "datetime", "today"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "datetime", "today"])) { return; } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcfromtimestamp.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcfromtimestamp.rs index fe14de1f726f5..26536d3c5cff7 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcfromtimestamp.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcfromtimestamp.rs @@ -8,6 +8,43 @@ use crate::checkers::ast::Checker; use super::helpers; +/// ## What it does +/// Checks for usage of `datetime.datetime.utcfromtimestamp()`. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.datetime.utcfromtimestamp()` returns a naive datetime object; +/// instead, use `datetime.datetime.fromtimestamp(ts, tz=)` to return a +/// timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.utcfromtimestamp() +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.fromtimestamp(946684800, tz=datetime.UTC) +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDatetimeUtcfromtimestamp; @@ -21,15 +58,6 @@ impl Violation for CallDatetimeUtcfromtimestamp { } } -/// Checks for `datetime.datetime.utcfromtimestamp()`. (DTZ004) -/// -/// ## Why is this bad? -/// -/// Because naive `datetime` objects are treated by many `datetime` methods as -/// local times, it is preferred to use aware datetimes to represent times in -/// UTC. As such, the recommended way to create an object representing a -/// specific timestamp in UTC is by calling `datetime.fromtimestamp(timestamp, -/// tz=timezone.utc)`. pub(crate) fn call_datetime_utcfromtimestamp( checker: &mut Checker, func: &Expr, @@ -38,7 +66,7 @@ pub(crate) fn call_datetime_utcfromtimestamp( if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["datetime", "datetime", "utcfromtimestamp"] diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcnow.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcnow.rs index 3c77bdef7ace5..e9ff0dd363180 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcnow.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_utcnow.rs @@ -8,6 +8,42 @@ use crate::checkers::ast::Checker; use super::helpers; +/// ## What it does +/// Checks for usage of `datetime.datetime.utcnow()`. +/// +/// ## Why is this bad? +/// Python datetime objects can be naive or timezone-aware. While an aware +/// object represents a specific moment in time, a naive object does not +/// contain enough information to unambiguously locate itself relative to other +/// datetime objects. Since this can lead to errors, it is recommended to +/// always use timezone-aware objects. +/// +/// `datetime.datetime.utcnow()` returns a naive datetime object; instead, use +/// `datetime.datetime.now(tz=)` to return a timezone-aware object. +/// +/// ## Example +/// ```python +/// import datetime +/// +/// datetime.datetime.utcnow() +/// ``` +/// +/// Use instead: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// +/// datetime.datetime.now(tz=datetime.UTC) +/// ``` +/// +/// ## References +/// - [Python documentation: Aware and Naive Objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) #[violation] pub struct CallDatetimeUtcnow; @@ -21,21 +57,11 @@ impl Violation for CallDatetimeUtcnow { } } -/// Checks for `datetime.datetime.today()`. (DTZ003) -/// -/// ## Why is this bad? -/// -/// Because naive `datetime` objects are treated by many `datetime` methods as -/// local times, it is preferred to use aware datetimes to represent times in -/// UTC. As such, the recommended way to create an object representing the -/// current time in UTC is by calling `datetime.now(timezone.utc)`. pub(crate) fn call_datetime_utcnow(checker: &mut Checker, func: &Expr, location: TextRange) { if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "datetime", "utcnow"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "datetime", "utcnow"])) { return; } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_without_tzinfo.rs b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_without_tzinfo.rs index 885d494e89bcc..cc0cb486a23f2 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_without_tzinfo.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/call_datetime_without_tzinfo.rs @@ -1,11 +1,10 @@ -use ruff_python_ast::{Expr, Keyword}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{has_non_none_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; +use crate::rules::flake8_datetimez::rules::helpers::has_non_none_keyword; use super::helpers; @@ -32,6 +31,13 @@ use super::helpers; /// ```python /// import datetime /// +/// datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc) +/// ``` +/// +/// Or, for Python 3.11 and later: +/// ```python +/// import datetime +/// /// datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.UTC) /// ``` #[violation] @@ -44,19 +50,11 @@ impl Violation for CallDatetimeWithoutTzinfo { } } -pub(crate) fn call_datetime_without_tzinfo( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], - location: TextRange, -) { +pub(crate) fn call_datetime_without_tzinfo(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "datetime"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "datetime"])) { return; } @@ -66,17 +64,17 @@ pub(crate) fn call_datetime_without_tzinfo( } // No positional arg: keyword is missing or constant None. - if args.len() < 8 && !has_non_none_keyword(keywords, "tzinfo") { + if call.arguments.args.len() < 8 && !has_non_none_keyword(&call.arguments, "tzinfo") { checker .diagnostics - .push(Diagnostic::new(CallDatetimeWithoutTzinfo, location)); + .push(Diagnostic::new(CallDatetimeWithoutTzinfo, call.range())); return; } // Positional arg: is constant None. - if args.len() >= 8 && is_const_none(&args[7]) { + if call.arguments.args.get(7).is_some_and(is_const_none) { checker .diagnostics - .push(Diagnostic::new(CallDatetimeWithoutTzinfo, location)); + .push(Diagnostic::new(CallDatetimeWithoutTzinfo, call.range())); } } diff --git a/crates/ruff/src/rules/flake8_datetimez/rules/helpers.rs b/crates/ruff/src/rules/flake8_datetimez/rules/helpers.rs index 1d08a627fd94a..21ab64dc7543e 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules/helpers.rs @@ -1,11 +1,19 @@ -use ruff_python_ast::{Expr, ExprAttribute}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{Arguments, Expr, ExprAttribute}; use crate::checkers::ast::Checker; /// Check if the parent expression is a call to `astimezone`. This assumes that /// the current expression is a `datetime.datetime` object. -pub(crate) fn parent_expr_is_astimezone(checker: &Checker) -> bool { - checker.semantic().expr_parent().map_or(false, |parent| { +pub(super) fn parent_expr_is_astimezone(checker: &Checker) -> bool { + checker.semantic().current_expression_parent().is_some_and( |parent| { matches!(parent, Expr::Attribute(ExprAttribute { attr, .. }) if attr.as_str() == "astimezone") }) } + +/// Return `true` if a keyword argument is present with a non-`None` value. +pub(super) fn has_non_none_keyword(arguments: &Arguments, keyword: &str) -> bool { + arguments + .find_keyword(keyword) + .is_some_and(|keyword| !is_const_none(&keyword.value)) +} diff --git a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs index 6ac8525032ff8..a54f7e08d260d 100644 --- a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -49,15 +49,18 @@ impl Violation for DjangoAllWithModelForm { /// DJ007 pub(crate) fn all_with_model_form( checker: &Checker, - bases: &[Expr], + arguments: Option<&Arguments>, body: &[Stmt], ) -> Option { - if !bases - .iter() - .any(|base| is_model_form(base, checker.semantic())) - { + if !arguments.is_some_and(|arguments| { + arguments + .args + .iter() + .any(|base| is_model_form(base, checker.semantic())) + }) { return None; } + for element in body { let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else { continue; @@ -80,13 +83,13 @@ pub(crate) fn all_with_model_form( continue; }; match value { - Constant::Str(s) => { - if s == "__all__" { + Constant::Str(ast::StringConstant { value, .. }) => { + if value == "__all__" { return Some(Diagnostic::new(DjangoAllWithModelForm, element.range())); } } - Constant::Bytes(b) => { - if b == "__all__".as_bytes() { + Constant::Bytes(ast::BytesConstant { value, .. }) => { + if value == "__all__".as_bytes() { return Some(Diagnostic::new(DjangoAllWithModelForm, element.range())); } } diff --git a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs index f56dd161ed677..af99c84cc8cc0 100644 --- a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -47,15 +47,18 @@ impl Violation for DjangoExcludeWithModelForm { /// DJ006 pub(crate) fn exclude_with_model_form( checker: &Checker, - bases: &[Expr], + arguments: Option<&Arguments>, body: &[Stmt], ) -> Option { - if !bases - .iter() - .any(|base| is_model_form(base, checker.semantic())) - { + if !arguments.is_some_and(|arguments| { + arguments + .args + .iter() + .any(|base| is_model_form(base, checker.semantic())) + }) { return None; } + for element in body { let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else { continue; diff --git a/crates/ruff/src/rules/flake8_django/rules/helpers.rs b/crates/ruff/src/rules/flake8_django/rules/helpers.rs index 2f7ca2408d7a6..c857bec150c11 100644 --- a/crates/ruff/src/rules/flake8_django/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_django/rules/helpers.rs @@ -4,14 +4,14 @@ use ruff_python_semantic::SemanticModel; /// Return `true` if a Python class appears to be a Django model, based on its base classes. pub(super) fn is_model(base: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(base).map_or(false, |call_path| { + semantic.resolve_call_path(base).is_some_and(|call_path| { matches!(call_path.as_slice(), ["django", "db", "models", "Model"]) }) } /// Return `true` if a Python class appears to be a Django model form, based on its base classes. pub(super) fn is_model_form(base: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(base).map_or(false, |call_path| { + semantic.resolve_call_path(base).is_some_and(|call_path| { matches!( call_path.as_slice(), ["django", "forms", "ModelForm"] | ["django", "forms", "models", "ModelForm"] @@ -21,7 +21,7 @@ pub(super) fn is_model_form(base: &Expr, semantic: &SemanticModel) -> bool { /// Return `true` if the expression is constructor for a Django model field. pub(super) fn is_model_field(expr: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { call_path .as_slice() .starts_with(&["django", "db", "models"]) diff --git a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs index a61866c8d88e8..eb7c62682ff15 100644 --- a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs +++ b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -45,47 +43,30 @@ impl Violation for DjangoLocalsInRenderFunction { } /// DJ003 -pub(crate) fn locals_in_render_function( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn locals_in_render_function(checker: &mut Checker, call: &ast::ExprCall) { if !checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["django", "shortcuts", "render"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["django", "shortcuts", "render"])) { return; } - let locals = if args.len() >= 3 { - if !is_locals_call(&args[2], checker.semantic()) { - return; + if let Some(argument) = call.arguments.find_argument("context", 2) { + if is_locals_call(argument, checker.semantic()) { + checker.diagnostics.push(Diagnostic::new( + DjangoLocalsInRenderFunction, + argument.range(), + )); } - &args[2] - } else if let Some(keyword) = find_keyword(keywords, "context") { - if !is_locals_call(&keyword.value, checker.semantic()) { - return; - } - &keyword.value - } else { - return; - }; - - checker.diagnostics.push(Diagnostic::new( - DjangoLocalsInRenderFunction, - locals.range(), - )); + } } fn is_locals_call(expr: &Expr, semantic: &SemanticModel) -> bool { let Expr::Call(ast::ExprCall { func, .. }) = expr else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "locals"]) - }) + semantic + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "locals"])) } diff --git a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs index f34b0b2e97ea1..ed310166bc66c 100644 --- a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs +++ b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -54,10 +54,13 @@ impl Violation for DjangoModelWithoutDunderStr { pub(crate) fn model_without_dunder_str( checker: &mut Checker, ast::StmtClassDef { - name, bases, body, .. + name, + arguments, + body, + .. }: &ast::StmtClassDef, ) { - if !is_non_abstract_model(bases, body, checker.semantic()) { + if !is_non_abstract_model(arguments.as_deref(), body, checker.semantic()) { return; } if has_dunder_method(body) { @@ -80,16 +83,20 @@ fn has_dunder_method(body: &[Stmt]) -> bool { }) } -fn is_non_abstract_model(bases: &[Expr], body: &[Stmt], semantic: &SemanticModel) -> bool { - for base in bases { - if is_model_abstract(body) { - continue; - } - if helpers::is_model(base, semantic) { - return true; - } +fn is_non_abstract_model( + arguments: Option<&Arguments>, + body: &[Stmt], + semantic: &SemanticModel, +) -> bool { + let Some(Arguments { args: bases, .. }) = arguments else { + return false; + }; + + if is_model_abstract(body) { + return false; } - false + + bases.iter().any(|base| helpers::is_model(base, semantic)) } /// Check if class is abstract, in terms of Django model inheritance. diff --git a/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs b/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs index 75c058255b473..fc75278c45046 100644 --- a/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs +++ b/crates/ruff/src/rules/flake8_django/rules/non_leading_receiver_decorator.rs @@ -52,11 +52,11 @@ impl Violation for DjangoNonLeadingReceiverDecorator { pub(crate) fn non_leading_receiver_decorator(checker: &mut Checker, decorator_list: &[Decorator]) { let mut seen_receiver = false; for (i, decorator) in decorator_list.iter().enumerate() { - let is_receiver = decorator.expression.as_call_expr().map_or(false, |call| { + let is_receiver = decorator.expression.as_call_expr().is_some_and(|call| { checker .semantic() .resolve_call_path(&call.func) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["django", "dispatch", "receiver"]) }) }); diff --git a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs index 3521b20601723..1d14bd14d56b2 100644 --- a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs +++ b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -69,7 +69,12 @@ pub(crate) fn nullable_model_string_field(checker: &mut Checker, body: &[Stmt]) } fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> { - let Expr::Call(ast::ExprCall { func, keywords, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { keywords, .. }, + .. + }) = value + else { return None; }; diff --git a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs index f01961cf6a922..c623842abc4f4 100644 --- a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs +++ b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs @@ -1,6 +1,6 @@ use std::fmt; -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -143,13 +143,15 @@ fn get_element_type(element: &Stmt, semantic: &SemanticModel) -> Option, body: &[Stmt], ) { - if !bases - .iter() - .any(|base| helpers::is_model(base, checker.semantic())) - { + if !arguments.is_some_and(|arguments| { + arguments + .args + .iter() + .any(|base| helpers::is_model(base, checker.semantic())) + }) { return; } diff --git a/crates/ruff/src/rules/flake8_errmsg/rules/string_in_exception.rs b/crates/ruff/src/rules/flake8_errmsg/rules/string_in_exception.rs index 5b60b40879e0f..928d6eb873d7c 100644 --- a/crates/ruff/src/rules/flake8_errmsg/rules/string_in_exception.rs +++ b/crates/ruff/src/rules/flake8_errmsg/rules/string_in_exception.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, ExprContext, Ranged, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, ExprContext, Ranged, Stmt}; use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -174,7 +174,11 @@ impl Violation for DotFormatInException { /// EM101, EM102, EM103 pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) { - if let Expr::Call(ast::ExprCall { args, .. }) = exc { + if let Expr::Call(ast::ExprCall { + arguments: Arguments { args, .. }, + .. + }) = exc + { if let Some(first) = args.first() { match first { // Check for string literals. @@ -206,7 +210,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr } } // Check for f-strings. - Expr::JoinedStr(_) => { + Expr::FString(_) => { if checker.enabled(Rule::FStringInException) { let mut diagnostic = Diagnostic::new(FStringInException, first.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/flake8_future_annotations/rules/future_required_type_annotation.rs b/crates/ruff/src/rules/flake8_future_annotations/rules/future_required_type_annotation.rs index 04835fad6ecb4..445b5c35de8da 100644 --- a/crates/ruff/src/rules/flake8_future_annotations/rules/future_required_type_annotation.rs +++ b/crates/ruff/src/rules/flake8_future_annotations/rules/future_required_type_annotation.rs @@ -20,6 +20,12 @@ use crate::checkers::ast::Checker; /// annotations at evaluation time, making the code compatible with both past /// and future Python versions. /// +/// This rule respects the [`target-version`] setting. For example, if your +/// project targets Python 3.10 and above, adding `from __future__ import annotations` +/// does not impact your ability to leverage PEP 604-style unions (e.g., to +/// convert `Optional[str]` to `str | None`). As such, this rule will only +/// flag such usages if your project targets Python 3.9 or below. +/// /// ## Example /// ```python /// def func(obj: dict[str, int | None]) -> None: @@ -34,6 +40,9 @@ use crate::checkers::ast::Checker; /// def func(obj: dict[str, int | None]) -> None: /// ... /// ``` +/// +/// ## Options +/// - `target-version` #[violation] pub struct FutureRequiredTypeAnnotation { reason: Reason, diff --git a/crates/ruff/src/rules/flake8_future_annotations/rules/future_rewritable_type_annotation.rs b/crates/ruff/src/rules/flake8_future_annotations/rules/future_rewritable_type_annotation.rs index df0998ddd40a5..5fb3f5708c02b 100644 --- a/crates/ruff/src/rules/flake8_future_annotations/rules/future_rewritable_type_annotation.rs +++ b/crates/ruff/src/rules/flake8_future_annotations/rules/future_rewritable_type_annotation.rs @@ -13,14 +13,25 @@ use crate::checkers::ast::Checker; /// /// ## Why is this bad? /// PEP 563 enabled the use of a number of convenient type annotations, such as -/// `list[str]` instead of `List[str]`, or `str | None` instead of -/// `Optional[str]`. However, these annotations are only available on Python -/// 3.9 and higher, _unless_ the `from __future__ import annotations` import is present. +/// `list[str]` instead of `List[str]`. However, these annotations are only +/// available on Python 3.9 and higher, _unless_ the `from __future__ import annotations` +/// import is present. +/// +/// Similarly, PEP 604 enabled the use of the `|` operator for unions, such as +/// `str | None` instead of `Optional[str]`. However, these annotations are only +/// available on Python 3.10 and higher, _unless_ the `from __future__ import annotations` +/// import is present. /// /// By adding the `__future__` import, the pyupgrade rules can automatically /// migrate existing code to use the new syntax, even for older Python versions. /// This rule thus pairs well with pyupgrade and with Ruff's pyupgrade rules. /// +/// This rule respects the [`target-version`] setting. For example, if your +/// project targets Python 3.10 and above, adding `from __future__ import annotations` +/// does not impact your ability to leverage PEP 604-style unions (e.g., to +/// convert `Optional[str]` to `str | None`). As such, this rule will only +/// flag such usages if your project targets Python 3.9 or below. +/// /// ## Example /// ```python /// from typing import List, Dict, Optional diff --git a/crates/ruff/src/rules/flake8_gettext/rules/f_string_in_gettext_func_call.rs b/crates/ruff/src/rules/flake8_gettext/rules/f_string_in_gettext_func_call.rs index ed781aeb12e4b..2b38343ad7202 100644 --- a/crates/ruff/src/rules/flake8_gettext/rules/f_string_in_gettext_func_call.rs +++ b/crates/ruff/src/rules/flake8_gettext/rules/f_string_in_gettext_func_call.rs @@ -52,7 +52,7 @@ impl Violation for FStringInGetTextFuncCall { /// INT001 pub(crate) fn f_string_in_gettext_func_call(checker: &mut Checker, args: &[Expr]) { if let Some(first) = args.first() { - if first.is_joined_str_expr() { + if first.is_f_string_expr() { checker .diagnostics .push(Diagnostic::new(FStringInGetTextFuncCall {}, first.range())); diff --git a/crates/ruff/src/rules/flake8_implicit_str_concat/rules/explicit.rs b/crates/ruff/src/rules/flake8_implicit_str_concat/rules/explicit.rs index 54629f288db56..f34fb79fa7c9e 100644 --- a/crates/ruff/src/rules/flake8_implicit_str_concat/rules/explicit.rs +++ b/crates/ruff/src/rules/flake8_implicit_str_concat/rules/explicit.rs @@ -50,14 +50,14 @@ pub(crate) fn explicit(expr: &Expr, locator: &Locator) -> Option { if matches!(op, Operator::Add) { if matches!( left.as_ref(), - Expr::JoinedStr(_) + Expr::FString(_) | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Bytes(..), .. }) ) && matches!( right.as_ref(), - Expr::JoinedStr(_) + Expr::FString(_) | Expr::Constant(ast::ExprConstant { value: Constant::Str(..) | Constant::Bytes(..), .. diff --git a/crates/ruff/src/rules/flake8_implicit_str_concat/rules/implicit.rs b/crates/ruff/src/rules/flake8_implicit_str_concat/rules/implicit.rs index 60d8ba496ff6d..e516cd56e8a51 100644 --- a/crates/ruff/src/rules/flake8_implicit_str_concat/rules/implicit.rs +++ b/crates/ruff/src/rules/flake8_implicit_str_concat/rules/implicit.rs @@ -126,8 +126,8 @@ pub(crate) fn implicit( } fn concatenate_strings(a_range: TextRange, b_range: TextRange, locator: &Locator) -> Option { - let a_text = &locator.contents()[a_range]; - let b_text = &locator.contents()[b_range]; + let a_text = locator.slice(a_range); + let b_text = locator.slice(b_range); let a_leading_quote = leading_quote(a_text)?; let b_leading_quote = leading_quote(b_text)?; diff --git a/crates/ruff/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs b/crates/ruff/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs index 628e7b167c8cb..4ee2cf7b46931 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs +++ b/crates/ruff/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs @@ -2,7 +2,8 @@ use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::Binding; +use ruff_python_ast::Ranged; +use ruff_python_semantic::{Binding, Imported}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -56,11 +57,13 @@ pub(crate) fn unconventional_import_alias( binding: &Binding, conventions: &FxHashMap, ) -> Option { - let Some(qualified_name) = binding.qualified_name() else { + let Some(import) = binding.as_any_import() else { return None; }; - let Some(expected_alias) = conventions.get(qualified_name) else { + let qualified_name = import.qualified_name(); + + let Some(expected_alias) = conventions.get(qualified_name.as_str()) else { return None; }; @@ -71,19 +74,21 @@ pub(crate) fn unconventional_import_alias( let mut diagnostic = Diagnostic::new( UnconventionalImportAlias { - name: qualified_name.to_string(), + name: qualified_name, asname: expected_alias.to_string(), }, - binding.range, + binding.range(), ); if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_available(expected_alias) { - diagnostic.try_set_fix(|| { - let scope = &checker.semantic().scopes[binding.scope]; - let (edit, rest) = - Renamer::rename(name, expected_alias, scope, checker.semantic())?; - Ok(Fix::suggested_edits(edit, rest)) - }); + if !import.is_submodule_import() { + if checker.semantic().is_available(expected_alias) { + diagnostic.try_set_fix(|| { + let scope = &checker.semantic().scopes[binding.scope]; + let (edit, rest) = + Renamer::rename(name, expected_alias, scope, checker.semantic())?; + Ok(Fix::suggested_edits(edit, rest)) + }); + } } } Some(diagnostic) diff --git a/crates/ruff/src/rules/flake8_import_conventions/settings.rs b/crates/ruff/src/rules/flake8_import_conventions/settings.rs index d5a038b54cc82..640aa9509628b 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/settings.rs +++ b/crates/ruff/src/rules/flake8_import_conventions/settings.rs @@ -9,6 +9,7 @@ const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[ ("altair", "alt"), ("matplotlib", "mpl"), ("matplotlib.pyplot", "plt"), + ("networkx", "nx"), ("numpy", "np"), ("pandas", "pd"), ("seaborn", "sns"), diff --git a/crates/ruff/src/rules/flake8_import_conventions/snapshots/ruff__rules__flake8_import_conventions__tests__defaults.snap b/crates/ruff/src/rules/flake8_import_conventions/snapshots/ruff__rules__flake8_import_conventions__tests__defaults.snap index 9197e9486ac29..5cd38193f6830 100644 --- a/crates/ruff/src/rules/flake8_import_conventions/snapshots/ruff__rules__flake8_import_conventions__tests__defaults.snap +++ b/crates/ruff/src/rules/flake8_import_conventions/snapshots/ruff__rules__flake8_import_conventions__tests__defaults.snap @@ -1,132 +1,282 @@ --- source: crates/ruff/src/rules/flake8_import_conventions/mod.rs --- -defaults.py:3:8: ICN001 `altair` should be imported as `alt` +defaults.py:6:12: ICN001 [*] `altair` should be imported as `alt` | -1 | import math # not checked -2 | -3 | import altair # unconventional - | ^^^^^^ ICN001 -4 | import matplotlib.pyplot # unconventional -5 | import numpy # unconventional +5 | def unconventional(): +6 | import altair + | ^^^^^^ ICN001 +7 | import matplotlib.pyplot +8 | import numpy | = help: Alias `altair` to `alt` -defaults.py:4:8: ICN001 `matplotlib.pyplot` should be imported as `plt` +ℹ Suggested fix +3 3 | +4 4 | +5 5 | def unconventional(): +6 |- import altair + 6 |+ import altair as alt +7 7 | import matplotlib.pyplot +8 8 | import numpy +9 9 | import pandas + +defaults.py:7:12: ICN001 `matplotlib.pyplot` should be imported as `plt` | -3 | import altair # unconventional -4 | import matplotlib.pyplot # unconventional - | ^^^^^^^^^^^^^^^^^ ICN001 -5 | import numpy # unconventional -6 | import pandas # unconventional +5 | def unconventional(): +6 | import altair +7 | import matplotlib.pyplot + | ^^^^^^^^^^^^^^^^^ ICN001 +8 | import numpy +9 | import pandas | = help: Alias `matplotlib.pyplot` to `plt` -defaults.py:5:8: ICN001 `numpy` should be imported as `np` - | -3 | import altair # unconventional -4 | import matplotlib.pyplot # unconventional -5 | import numpy # unconventional - | ^^^^^ ICN001 -6 | import pandas # unconventional -7 | import seaborn # unconventional - | - = help: Alias `numpy` to `np` +defaults.py:8:12: ICN001 [*] `numpy` should be imported as `np` + | + 6 | import altair + 7 | import matplotlib.pyplot + 8 | import numpy + | ^^^^^ ICN001 + 9 | import pandas +10 | import seaborn + | + = help: Alias `numpy` to `np` -defaults.py:6:8: ICN001 `pandas` should be imported as `pd` - | -4 | import matplotlib.pyplot # unconventional -5 | import numpy # unconventional -6 | import pandas # unconventional - | ^^^^^^ ICN001 -7 | import seaborn # unconventional -8 | import tkinter # unconventional - | - = help: Alias `pandas` to `pd` +ℹ Suggested fix +5 5 | def unconventional(): +6 6 | import altair +7 7 | import matplotlib.pyplot +8 |- import numpy + 8 |+ import numpy as np +9 9 | import pandas +10 10 | import seaborn +11 11 | import tkinter -defaults.py:7:8: ICN001 `seaborn` should be imported as `sns` - | -5 | import numpy # unconventional -6 | import pandas # unconventional -7 | import seaborn # unconventional - | ^^^^^^^ ICN001 -8 | import tkinter # unconventional - | - = help: Alias `seaborn` to `sns` +defaults.py:9:12: ICN001 [*] `pandas` should be imported as `pd` + | + 7 | import matplotlib.pyplot + 8 | import numpy + 9 | import pandas + | ^^^^^^ ICN001 +10 | import seaborn +11 | import tkinter + | + = help: Alias `pandas` to `pd` + +ℹ Suggested fix +6 6 | import altair +7 7 | import matplotlib.pyplot +8 8 | import numpy +9 |- import pandas + 9 |+ import pandas as pd +10 10 | import seaborn +11 11 | import tkinter +12 12 | import networkx + +defaults.py:10:12: ICN001 [*] `seaborn` should be imported as `sns` + | + 8 | import numpy + 9 | import pandas +10 | import seaborn + | ^^^^^^^ ICN001 +11 | import tkinter +12 | import networkx + | + = help: Alias `seaborn` to `sns` + +ℹ Suggested fix +7 7 | import matplotlib.pyplot +8 8 | import numpy +9 9 | import pandas +10 |- import seaborn + 10 |+ import seaborn as sns +11 11 | import tkinter +12 12 | import networkx +13 13 | -defaults.py:8:8: ICN001 `tkinter` should be imported as `tk` +defaults.py:11:12: ICN001 [*] `tkinter` should be imported as `tk` | - 6 | import pandas # unconventional - 7 | import seaborn # unconventional - 8 | import tkinter # unconventional - | ^^^^^^^ ICN001 - 9 | -10 | import altair as altr # unconventional + 9 | import pandas +10 | import seaborn +11 | import tkinter + | ^^^^^^^ ICN001 +12 | import networkx | = help: Alias `tkinter` to `tk` -defaults.py:10:18: ICN001 `altair` should be imported as `alt` +ℹ Suggested fix +8 8 | import numpy +9 9 | import pandas +10 10 | import seaborn +11 |- import tkinter + 11 |+ import tkinter as tk +12 12 | import networkx +13 13 | +14 14 | + +defaults.py:12:12: ICN001 [*] `networkx` should be imported as `nx` | - 8 | import tkinter # unconventional - 9 | -10 | import altair as altr # unconventional - | ^^^^ ICN001 -11 | import matplotlib.pyplot as plot # unconventional -12 | import numpy as nmp # unconventional +10 | import seaborn +11 | import tkinter +12 | import networkx + | ^^^^^^^^ ICN001 + | + = help: Alias `networkx` to `nx` + +ℹ Suggested fix +9 9 | import pandas +10 10 | import seaborn +11 11 | import tkinter +12 |- import networkx + 12 |+ import networkx as nx +13 13 | +14 14 | +15 15 | def unconventional_aliases(): + +defaults.py:16:22: ICN001 [*] `altair` should be imported as `alt` + | +15 | def unconventional_aliases(): +16 | import altair as altr + | ^^^^ ICN001 +17 | import matplotlib.pyplot as plot +18 | import numpy as nmp | = help: Alias `altair` to `alt` -defaults.py:11:29: ICN001 `matplotlib.pyplot` should be imported as `plt` +ℹ Suggested fix +13 13 | +14 14 | +15 15 | def unconventional_aliases(): +16 |- import altair as altr + 16 |+ import altair as alt +17 17 | import matplotlib.pyplot as plot +18 18 | import numpy as nmp +19 19 | import pandas as pdas + +defaults.py:17:33: ICN001 [*] `matplotlib.pyplot` should be imported as `plt` | -10 | import altair as altr # unconventional -11 | import matplotlib.pyplot as plot # unconventional - | ^^^^ ICN001 -12 | import numpy as nmp # unconventional -13 | import pandas as pdas # unconventional +15 | def unconventional_aliases(): +16 | import altair as altr +17 | import matplotlib.pyplot as plot + | ^^^^ ICN001 +18 | import numpy as nmp +19 | import pandas as pdas | = help: Alias `matplotlib.pyplot` to `plt` -defaults.py:12:17: ICN001 `numpy` should be imported as `np` +ℹ Suggested fix +14 14 | +15 15 | def unconventional_aliases(): +16 16 | import altair as altr +17 |- import matplotlib.pyplot as plot + 17 |+ import matplotlib.pyplot as plt +18 18 | import numpy as nmp +19 19 | import pandas as pdas +20 20 | import seaborn as sbrn + +defaults.py:18:21: ICN001 [*] `numpy` should be imported as `np` | -10 | import altair as altr # unconventional -11 | import matplotlib.pyplot as plot # unconventional -12 | import numpy as nmp # unconventional - | ^^^ ICN001 -13 | import pandas as pdas # unconventional -14 | import seaborn as sbrn # unconventional +16 | import altair as altr +17 | import matplotlib.pyplot as plot +18 | import numpy as nmp + | ^^^ ICN001 +19 | import pandas as pdas +20 | import seaborn as sbrn | = help: Alias `numpy` to `np` -defaults.py:13:18: ICN001 `pandas` should be imported as `pd` +ℹ Suggested fix +15 15 | def unconventional_aliases(): +16 16 | import altair as altr +17 17 | import matplotlib.pyplot as plot +18 |- import numpy as nmp + 18 |+ import numpy as np +19 19 | import pandas as pdas +20 20 | import seaborn as sbrn +21 21 | import tkinter as tkr + +defaults.py:19:22: ICN001 [*] `pandas` should be imported as `pd` | -11 | import matplotlib.pyplot as plot # unconventional -12 | import numpy as nmp # unconventional -13 | import pandas as pdas # unconventional - | ^^^^ ICN001 -14 | import seaborn as sbrn # unconventional -15 | import tkinter as tkr # unconventional +17 | import matplotlib.pyplot as plot +18 | import numpy as nmp +19 | import pandas as pdas + | ^^^^ ICN001 +20 | import seaborn as sbrn +21 | import tkinter as tkr | = help: Alias `pandas` to `pd` -defaults.py:14:19: ICN001 `seaborn` should be imported as `sns` +ℹ Suggested fix +16 16 | import altair as altr +17 17 | import matplotlib.pyplot as plot +18 18 | import numpy as nmp +19 |- import pandas as pdas + 19 |+ import pandas as pd +20 20 | import seaborn as sbrn +21 21 | import tkinter as tkr +22 22 | import networkx as nxy + +defaults.py:20:23: ICN001 [*] `seaborn` should be imported as `sns` | -12 | import numpy as nmp # unconventional -13 | import pandas as pdas # unconventional -14 | import seaborn as sbrn # unconventional - | ^^^^ ICN001 -15 | import tkinter as tkr # unconventional +18 | import numpy as nmp +19 | import pandas as pdas +20 | import seaborn as sbrn + | ^^^^ ICN001 +21 | import tkinter as tkr +22 | import networkx as nxy | = help: Alias `seaborn` to `sns` -defaults.py:15:19: ICN001 `tkinter` should be imported as `tk` +ℹ Suggested fix +17 17 | import matplotlib.pyplot as plot +18 18 | import numpy as nmp +19 19 | import pandas as pdas +20 |- import seaborn as sbrn + 20 |+ import seaborn as sns +21 21 | import tkinter as tkr +22 22 | import networkx as nxy +23 23 | + +defaults.py:21:23: ICN001 [*] `tkinter` should be imported as `tk` | -13 | import pandas as pdas # unconventional -14 | import seaborn as sbrn # unconventional -15 | import tkinter as tkr # unconventional - | ^^^ ICN001 -16 | -17 | import altair as alt # conventional +19 | import pandas as pdas +20 | import seaborn as sbrn +21 | import tkinter as tkr + | ^^^ ICN001 +22 | import networkx as nxy | = help: Alias `tkinter` to `tk` +ℹ Suggested fix +18 18 | import numpy as nmp +19 19 | import pandas as pdas +20 20 | import seaborn as sbrn +21 |- import tkinter as tkr + 21 |+ import tkinter as tk +22 22 | import networkx as nxy +23 23 | +24 24 | def conventional_aliases(): + +defaults.py:22:24: ICN001 [*] `networkx` should be imported as `nx` + | +20 | import seaborn as sbrn +21 | import tkinter as tkr +22 | import networkx as nxy + | ^^^ ICN001 +23 | +24 | def conventional_aliases(): + | + = help: Alias `networkx` to `nx` + +ℹ Suggested fix +19 19 | import pandas as pdas +20 20 | import seaborn as sbrn +21 21 | import tkinter as tkr +22 |- import networkx as nxy + 22 |+ import networkx as nx +23 23 | +24 24 | def conventional_aliases(): +25 25 | import altair as alt + diff --git a/crates/ruff/src/rules/flake8_logging_format/rules/logging_call.rs b/crates/ruff/src/rules/flake8_logging_format/rules/logging_call.rs index b3d9125cb664c..0a9cc72ecc71f 100644 --- a/crates/ruff/src/rules/flake8_logging_format/rules/logging_call.rs +++ b/crates/ruff/src/rules/flake8_logging_format/rules/logging_call.rs @@ -1,7 +1,5 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Operator, Ranged}; - use ruff_diagnostics::{Diagnostic, Edit, Fix}; -use ruff_python_ast::helpers::{find_keyword, CallArguments}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Keyword, Operator, Ranged}; use ruff_python_semantic::analyze::logging; use ruff_python_stdlib::logging::LoggingLevel; @@ -64,7 +62,7 @@ fn check_msg(checker: &mut Checker, msg: &Expr) { _ => {} }, // Check for f-strings. - Expr::JoinedStr(_) => { + Expr::FString(_) => { if checker.enabled(Rule::LoggingFString) { checker .diagnostics @@ -108,13 +106,15 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) { } } } - Expr::Call(ast::ExprCall { func, keywords, .. }) => { + Expr::Call(ast::ExprCall { + func, + arguments: Arguments { keywords, .. }, + .. + }) => { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "dict"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "dict"])) { for keyword in keywords { if let Some(attr) = &keyword.arg { @@ -151,13 +151,8 @@ impl LoggingCallType { } /// Check logging calls for violations. -pub(crate) fn logging_call( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { - let Expr::Attribute(ast::ExprAttribute { value: _, attr, .. }) = func else { +pub(crate) fn logging_call(checker: &mut Checker, call: &ast::ExprCall) { + let Expr::Attribute(ast::ExprAttribute { value: _, attr, .. }) = call.func.as_ref() else { return; }; @@ -165,13 +160,17 @@ pub(crate) fn logging_call( return; }; - if !logging::is_logger_candidate(func, checker.semantic(), &checker.settings.logger_objects) { + if !logging::is_logger_candidate( + &call.func, + checker.semantic(), + &checker.settings.logger_objects, + ) { return; } // G001 - G004 let msg_pos = usize::from(matches!(logging_call_type, LoggingCallType::LogCall)); - if let Some(format_arg) = CallArguments::new(args, keywords).argument("msg", msg_pos) { + if let Some(format_arg) = call.arguments.find_argument("msg", msg_pos) { check_msg(checker, format_arg); } @@ -194,7 +193,7 @@ pub(crate) fn logging_call( // G101 if checker.enabled(Rule::LoggingExtraAttrClash) { - if let Some(extra) = find_keyword(keywords, "extra") { + if let Some(extra) = call.arguments.find_keyword("extra") { check_log_record_attr_clash(checker, extra); } } @@ -204,7 +203,7 @@ pub(crate) fn logging_call( if !checker.semantic().in_exception_handler() { return; } - let Some(exc_info) = logging::exc_info(keywords, checker.semantic()) else { + let Some(exc_info) = logging::exc_info(&call.arguments, checker.semantic()) else { return; }; if let LoggingCallType::LevelCall(logging_level) = logging_call_type { diff --git a/crates/ruff/src/rules/flake8_logging_format/snapshots/ruff__rules__flake8_logging_format__tests__G004.py.snap b/crates/ruff/src/rules/flake8_logging_format/snapshots/ruff__rules__flake8_logging_format__tests__G004.py.snap index b94da46ca98f2..b54d2a4862767 100644 --- a/crates/ruff/src/rules/flake8_logging_format/snapshots/ruff__rules__flake8_logging_format__tests__G004.py.snap +++ b/crates/ruff/src/rules/flake8_logging_format/snapshots/ruff__rules__flake8_logging_format__tests__G004.py.snap @@ -15,6 +15,15 @@ G004.py:5:27: G004 Logging statement uses f-string 4 | logging.info(f"Hello {name}") 5 | logging.log(logging.INFO, f"Hello {name}") | ^^^^^^^^^^^^^^^ G004 +6 | +7 | _LOGGER = logging.getLogger() + | + +G004.py:8:14: G004 Logging statement uses f-string + | +7 | _LOGGER = logging.getLogger() +8 | _LOGGER.info(f"{__name__}") + | ^^^^^^^^^^^^^ G004 | diff --git a/crates/ruff/src/rules/flake8_logging_format/violations.rs b/crates/ruff/src/rules/flake8_logging_format/violations.rs index 3bada9ec59658..77a96c7fce53f 100644 --- a/crates/ruff/src/rules/flake8_logging_format/violations.rs +++ b/crates/ruff/src/rules/flake8_logging_format/violations.rs @@ -21,6 +21,19 @@ use ruff_macros::{derive_message_formats, violation}; /// As an alternative to `extra`, passing values as arguments to the logging /// method can also be used to defer string formatting until required. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -54,6 +67,9 @@ use ruff_macros::{derive_message_formats, violation}; /// logging.info("%s - Something happened", user) /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging`](https://docs.python.org/3/library/logging.html) /// - [Python documentation: Optimization](https://docs.python.org/3/howto/logging.html#optimization) @@ -89,6 +105,19 @@ impl Violation for LoggingStringFormat { /// As an alternative to `extra`, passing values as arguments to the logging /// method can also be used to defer string formatting until required. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -122,6 +151,9 @@ impl Violation for LoggingStringFormat { /// logging.info("%s - Something happened", user) /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging`](https://docs.python.org/3/library/logging.html) /// - [Python documentation: Optimization](https://docs.python.org/3/howto/logging.html#optimization) @@ -156,6 +188,19 @@ impl Violation for LoggingPercentFormat { /// As an alternative to `extra`, passing values as arguments to the logging /// method can also be used to defer string formatting until required. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -189,6 +234,9 @@ impl Violation for LoggingPercentFormat { /// logging.info("%s - Something happened", user) /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging`](https://docs.python.org/3/library/logging.html) /// - [Python documentation: Optimization](https://docs.python.org/3/howto/logging.html#optimization) @@ -222,6 +270,19 @@ impl Violation for LoggingStringConcat { /// As an alternative to `extra`, passing values as arguments to the logging /// method can also be used to defer string formatting until required. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -255,6 +316,9 @@ impl Violation for LoggingStringConcat { /// logging.info("%s - Something happened", user) /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging`](https://docs.python.org/3/library/logging.html) /// - [Python documentation: Optimization](https://docs.python.org/3/howto/logging.html#optimization) @@ -276,6 +340,19 @@ impl Violation for LoggingFString { /// `logging.warning` and `logging.Logger.warning`, which are functionally /// equivalent. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -290,6 +367,9 @@ impl Violation for LoggingFString { /// logging.warning("Something happened") /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging.warning`](https://docs.python.org/3/library/logging.html#logging.warning) /// - [Python documentation: `logging.Logger.warning`](https://docs.python.org/3/library/logging.html#logging.Logger.warning) @@ -320,6 +400,19 @@ impl AlwaysAutofixableViolation for LoggingWarn { /// the `LogRecord` constructor will raise a `KeyError` when the `LogRecord` is /// constructed. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -342,6 +435,9 @@ impl AlwaysAutofixableViolation for LoggingWarn { /// logging.info("Something happened", extra=dict(user=username)) /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: LogRecord attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes) #[violation] @@ -365,6 +461,19 @@ impl Violation for LoggingExtraAttrClash { /// `logging.exception`. Using `logging.exception` is more concise, more /// readable, and conveys the intent of the logging statement more clearly. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -385,6 +494,9 @@ impl Violation for LoggingExtraAttrClash { /// logging.exception("Exception occurred") /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception) /// - [Python documentation: `exception`](https://docs.python.org/3/library/logging.html#logging.Logger.exception) @@ -410,6 +522,19 @@ impl Violation for LoggingExcInfo { /// Passing `exc_info=True` to `logging.exception` calls is redundant, as is /// passing `exc_info=False` to `logging.error` calls. /// +/// ## Known problems +/// +/// This rule detects uses of the `logging` module via a heuristic. +/// Specifically, it matches against: +/// +/// - Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`). +/// - Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`). +/// - Objects whose name starts with `log` or ends with `logger` or `logging`, +/// when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`). +/// - Imported objects marked as loggers via the [`logger-objects`] setting, which can be +/// used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`, +/// when [`logger-objects`] is set to `["module.logger"]`). +/// /// ## Example /// ```python /// import logging @@ -430,6 +555,9 @@ impl Violation for LoggingExcInfo { /// logging.exception("Exception occurred") /// ``` /// +/// ## Options +/// - `logger-objects` +/// /// ## References /// - [Python documentation: `logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception) /// - [Python documentation: `exception`](https://docs.python.org/3/library/logging.html#logging.Logger.exception) diff --git a/crates/ruff/src/rules/flake8_no_pep420/rules/implicit_namespace_package.rs b/crates/ruff/src/rules/flake8_no_pep420/rules/implicit_namespace_package.rs index 5c2a8ae4f8580..a8e0508f2a96d 100644 --- a/crates/ruff/src/rules/flake8_no_pep420/rules/implicit_namespace_package.rs +++ b/crates/ruff/src/rules/flake8_no_pep420/rules/implicit_namespace_package.rs @@ -47,15 +47,15 @@ pub(crate) fn implicit_namespace_package( ) -> Option { if package.is_none() // Ignore non-`.py` files, which don't require an `__init__.py`. - && path.extension().map_or(false, |ext| ext == "py") + && path.extension().is_some_and( |ext| ext == "py") // Ignore any files that are direct children of the project root. && !path .parent() - .map_or(false, |parent| parent == project_root) + .is_some_and( |parent| parent == project_root) // Ignore any files that are direct children of a source directory (e.g., `src/manage.py`). && !path .parent() - .map_or(false, |parent| src.iter().any(|src| src == parent)) + .is_some_and( |parent| src.iter().any(|src| src == parent)) { #[cfg(all(test, windows))] let path = path diff --git a/crates/ruff/src/rules/flake8_pie/mod.rs b/crates/ruff/src/rules/flake8_pie/mod.rs index a1cfb8349c99a..d31962dc28c3a 100644 --- a/crates/ruff/src/rules/flake8_pie/mod.rs +++ b/crates/ruff/src/rules/flake8_pie/mod.rs @@ -15,6 +15,7 @@ mod tests { #[test_case(Rule::DuplicateClassFieldDefinition, Path::new("PIE794.py"))] #[test_case(Rule::UnnecessaryDictKwargs, Path::new("PIE804.py"))] #[test_case(Rule::MultipleStartsEndsWith, Path::new("PIE810.py"))] + #[test_case(Rule::UnnecessaryRangeStart, Path::new("PIE808.py"))] #[test_case(Rule::UnnecessaryPass, Path::new("PIE790.py"))] #[test_case(Rule::UnnecessarySpread, Path::new("PIE800.py"))] #[test_case(Rule::ReimplementedListBuiltin, Path::new("PIE807.py"))] diff --git a/crates/ruff/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs b/crates/ruff/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs index 34cd5190b044c..df9a36c219a3b 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs @@ -1,9 +1,9 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use rustc_hash::FxHashSet; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::{AlwaysAutofixableViolation, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use crate::autofix; use crate::checkers::ast::Checker; @@ -49,11 +49,7 @@ impl AlwaysAutofixableViolation for DuplicateClassFieldDefinition { } /// PIE794 -pub(crate) fn duplicate_class_field_definition( - checker: &mut Checker, - parent: &Stmt, - body: &[Stmt], -) { +pub(crate) fn duplicate_class_field_definition(checker: &mut Checker, body: &[Stmt]) { let mut seen_targets: FxHashSet<&str> = FxHashSet::default(); for stmt in body { // Extract the property name from the assignment statement. @@ -85,11 +81,13 @@ pub(crate) fn duplicate_class_field_definition( if checker.patch(diagnostic.kind.rule()) { let edit = autofix::edits::delete_stmt( stmt, - Some(parent), + Some(stmt), checker.locator(), checker.indexer(), ); - diagnostic.set_fix(Fix::suggested(edit).isolate(checker.isolation(Some(parent)))); + diagnostic.set_fix(Fix::suggested(edit).isolate(Checker::isolation(Some( + checker.semantic().current_statement_id(), + )))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_pie/rules/mod.rs b/crates/ruff/src/rules/flake8_pie/rules/mod.rs index e86cd7a19dc51..79012144acf6d 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/mod.rs @@ -4,6 +4,7 @@ pub(crate) use no_unnecessary_pass::*; pub(crate) use non_unique_enums::*; pub(crate) use reimplemented_list_builtin::*; pub(crate) use unnecessary_dict_kwargs::*; +pub(crate) use unnecessary_range_start::*; pub(crate) use unnecessary_spread::*; mod duplicate_class_field_definition; @@ -12,4 +13,5 @@ mod no_unnecessary_pass; mod non_unique_enums; mod reimplemented_list_builtin; mod unnecessary_dict_kwargs; +mod unnecessary_range_start; mod unnecessary_spread; diff --git a/crates/ruff/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs b/crates/ruff/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs index 3050bbc2bd063..c071007f60a47 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs @@ -5,7 +5,7 @@ use itertools::Either::{Left, Right}; use ruff_text_size::TextRange; -use ruff_python_ast::{self as ast, BoolOp, Expr, ExprContext, Identifier, Ranged}; +use ruff_python_ast::{self as ast, Arguments, BoolOp, Expr, ExprContext, Identifier, Ranged}; use ruff_diagnostics::AlwaysAutofixableViolation; use ruff_diagnostics::{Diagnostic, Edit, Fix}; @@ -73,8 +73,12 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { for (index, call) in values.iter().enumerate() { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) = &call else { @@ -118,8 +122,12 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { .map(|expr| { let Expr::Call(ast::ExprCall { func: _, - args, - keywords: _, + arguments: + Arguments { + args, + keywords: _, + range: _, + }, range: _, }) = expr else { @@ -161,8 +169,11 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { }); let node3 = Expr::Call(ast::ExprCall { func: Box::new(node2), - args: vec![node], - keywords: vec![], + arguments: Arguments { + args: vec![node], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }); let call = node3; diff --git a/crates/ruff/src/rules/flake8_pie/rules/no_unnecessary_pass.rs b/crates/ruff/src/rules/flake8_pie/rules/no_unnecessary_pass.rs index ee7fa6acfc7d7..96999f479ce24 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/no_unnecessary_pass.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/no_unnecessary_pass.rs @@ -50,28 +50,28 @@ impl AlwaysAutofixableViolation for UnnecessaryPass { /// PIE790 pub(crate) fn no_unnecessary_pass(checker: &mut Checker, body: &[Stmt]) { - if body.len() > 1 { - // This only catches the case in which a docstring makes a `pass` statement - // redundant. Consider removing all `pass` statements instead. - if !is_docstring_stmt(&body[0]) { - return; - } + let [first, second, ..] = body else { + return; + }; + // This only catches the case in which a docstring makes a `pass` statement + // redundant. Consider removing all `pass` statements instead. + if !is_docstring_stmt(first) { + return; + } - // The second statement must be a `pass` statement. - let stmt = &body[1]; - if !stmt.is_pass_stmt() { - return; - } + // The second statement must be a `pass` statement. + if !second.is_pass_stmt() { + return; + } - let mut diagnostic = Diagnostic::new(UnnecessaryPass, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = if let Some(index) = trailing_comment_start_offset(stmt, checker.locator()) { - Edit::range_deletion(stmt.range().add_end(index)) - } else { - autofix::edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()) - }; - diagnostic.set_fix(Fix::automatic(edit)); - } - checker.diagnostics.push(diagnostic); + let mut diagnostic = Diagnostic::new(UnnecessaryPass, second.range()); + if checker.patch(diagnostic.kind.rule()) { + let edit = if let Some(index) = trailing_comment_start_offset(second, checker.locator()) { + Edit::range_deletion(second.range().add_end(index)) + } else { + autofix::edits::delete_stmt(second, None, checker.locator(), checker.indexer()) + }; + diagnostic.set_fix(Fix::automatic(edit)); } + checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_pie/rules/non_unique_enums.rs b/crates/ruff/src/rules/flake8_pie/rules/non_unique_enums.rs index 81ed597a39ace..7603fa3d44bd1 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/non_unique_enums.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/non_unique_enums.rs @@ -1,10 +1,10 @@ -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use rustc_hash::FxHashSet; use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use crate::checkers::ast::Checker; @@ -54,17 +54,15 @@ impl Violation for NonUniqueEnums { /// PIE796 pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stmt]) { - let Stmt::ClassDef(ast::StmtClassDef { bases, .. }) = parent else { + let Stmt::ClassDef(parent) = parent else { return; }; - if !bases.iter().any(|expr| { + if !parent.bases().iter().any(|expr| { checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["enum", "Enum"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["enum", "Enum"])) }) { return; } @@ -79,9 +77,7 @@ pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stm if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["enum", "auto"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["enum", "auto"])) { continue; } diff --git a/crates/ruff/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs b/crates/ruff/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs index fc1348672e6e5..2c5a8bae51231 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs @@ -54,17 +54,12 @@ impl Violation for ReimplementedListBuiltin { /// PIE807 pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambda) { let ExprLambda { - args, + parameters, body, range: _, } = expr; - if args.args.is_empty() - && args.kwonlyargs.is_empty() - && args.posonlyargs.is_empty() - && args.vararg.is_none() - && args.kwarg.is_none() - { + if parameters.is_none() { if let Expr::List(ast::ExprList { elts, .. }) = body.as_ref() { if elts.is_empty() { let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range()); diff --git a/crates/ruff/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs b/crates/ruff/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs index 42b24fcb7137a..92f14a08f597a 100644 --- a/crates/ruff/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs +++ b/crates/ruff/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs @@ -53,7 +53,7 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs if kw.arg.is_none() { if let Expr::Dict(ast::ExprDict { keys, .. }) = &kw.value { // ensure foo(**{"bar-bar": 1}) doesn't error - if keys.iter().all(|expr| expr.as_ref().map_or(false, is_valid_kwarg_name)) || + if keys.iter().all(|expr| expr.as_ref().is_some_and( is_valid_kwarg_name)) || // handle case of foo(**{**bar}) (keys.len() == 1 && keys[0].is_none()) { diff --git a/crates/ruff/src/rules/flake8_pie/rules/unnecessary_range_start.rs b/crates/ruff/src/rules/flake8_pie/rules/unnecessary_range_start.rs new file mode 100644 index 0000000000000..a6d619a432c45 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pie/rules/unnecessary_range_start.rs @@ -0,0 +1,94 @@ +use num_bigint::BigInt; + +use ruff_diagnostics::Diagnostic; +use ruff_diagnostics::{AlwaysAutofixableViolation, Fix}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; + +use crate::autofix::edits::{remove_argument, Parentheses}; +use crate::checkers::ast::Checker; +use crate::registry::AsRule; + +/// ## What it does +/// Checks for `range` calls with an unnecessary `start` argument. +/// +/// ## Why is this bad? +/// `range(0, x)` is equivalent to `range(x)`, as `0` is the default value for +/// the `start` argument. Omitting the `start` argument makes the code more +/// concise and idiomatic. +/// +/// ## Example +/// ```python +/// range(0, 3) +/// ``` +/// +/// Use instead: +/// ```python +/// range(3) +/// ``` +/// +/// ## References +/// - [Python documentation: `range`](https://docs.python.org/3/library/stdtypes.html#range) +#[violation] +pub struct UnnecessaryRangeStart; + +impl AlwaysAutofixableViolation for UnnecessaryRangeStart { + #[derive_message_formats] + fn message(&self) -> String { + format!("Unnecessary `start` argument in `range`") + } + + fn autofix_title(&self) -> String { + format!("Remove `start` argument") + } +} + +/// PIE808 +pub(crate) fn unnecessary_range_start(checker: &mut Checker, call: &ast::ExprCall) { + // Verify that the call is to the `range` builtin. + let Expr::Name(ast::ExprName { id, .. }) = call.func.as_ref() else { + return; + }; + if id != "range" { + return; + }; + if !checker.semantic().is_builtin("range") { + return; + }; + + // `range` doesn't accept keyword arguments. + if !call.arguments.keywords.is_empty() { + return; + } + + // Verify that the call has exactly two arguments (no `step`). + let [start, _] = call.arguments.args.as_slice() else { + return; + }; + + // Verify that the `start` argument is the literal `0`. + let Expr::Constant(ast::ExprConstant { + value: Constant::Int(value), + .. + }) = start + else { + return; + }; + if *value != BigInt::from(0) { + return; + }; + + let mut diagnostic = Diagnostic::new(UnnecessaryRangeStart, start.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.try_set_fix(|| { + remove_argument( + &start, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::automatic) + }); + } + checker.diagnostics.push(diagnostic); +} diff --git a/crates/ruff/src/rules/flake8_pie/snapshots/ruff__rules__flake8_pie__tests__PIE808_PIE808.py.snap b/crates/ruff/src/rules/flake8_pie/snapshots/ruff__rules__flake8_pie__tests__PIE808_PIE808.py.snap new file mode 100644 index 0000000000000..0215ece47a8cb --- /dev/null +++ b/crates/ruff/src/rules/flake8_pie/snapshots/ruff__rules__flake8_pie__tests__PIE808_PIE808.py.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/flake8_pie/mod.rs +--- +PIE808.py:2:7: PIE808 [*] Unnecessary `start` argument in `range` + | +1 | # PIE808 +2 | range(0, 10) + | ^ PIE808 +3 | +4 | # OK + | + = help: Remove `start` argument + +ℹ Fix +1 1 | # PIE808 +2 |-range(0, 10) + 2 |+range(10) +3 3 | +4 4 | # OK +5 5 | range(x, 10) + + diff --git a/crates/ruff/src/rules/flake8_print/rules/print_call.rs b/crates/ruff/src/rules/flake8_print/rules/print_call.rs index 7cc8dbf26fef0..4b52aea891230 100644 --- a/crates/ruff/src/rules/flake8_print/rules/print_call.rs +++ b/crates/ruff/src/rules/flake8_print/rules/print_call.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_none}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -76,15 +75,16 @@ impl Violation for PPrint { } /// T201, T203 -pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn print_call(checker: &mut Checker, call: &ast::ExprCall) { let diagnostic = { - let call_path = checker.semantic().resolve_call_path(func); - if call_path.as_ref().map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "print"]) - }) { + let call_path = checker.semantic().resolve_call_path(&call.func); + if call_path + .as_ref() + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "print"])) + { // If the print call has a `file=` argument (that isn't `None`, `"sys.stdout"`, // or `"sys.stderr"`), don't trigger T201. - if let Some(keyword) = find_keyword(keywords, "file") { + if let Some(keyword) = call.arguments.find_keyword("file") { if !is_const_none(&keyword.value) { if checker.semantic().resolve_call_path(&keyword.value).map_or( true, @@ -97,11 +97,12 @@ pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword } } } - Diagnostic::new(Print, func.range()) - } else if call_path.as_ref().map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pprint", "pprint"]) - }) { - Diagnostic::new(PPrint, func.range()) + Diagnostic::new(Print, call.func.range()) + } else if call_path + .as_ref() + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pprint", "pprint"])) + { + Diagnostic::new(PPrint, call.func.range()) } else { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/mod.rs b/crates/ruff/src/rules/flake8_pyi/mod.rs index 6c363fdc6b397..c5c545a55bab0 100644 --- a/crates/ruff/src/rules/flake8_pyi/mod.rs +++ b/crates/ruff/src/rules/flake8_pyi/mod.rs @@ -10,6 +10,7 @@ mod tests { use test_case::test_case; use crate::registry::Rule; + use crate::settings::types::PythonVersion; use crate::test::test_path; use crate::{assert_messages, settings}; @@ -29,46 +30,50 @@ mod tests { #[test_case(Rule::ComplexAssignmentInStub, Path::new("PYI017.pyi"))] #[test_case(Rule::ComplexIfStatementInStub, Path::new("PYI002.py"))] #[test_case(Rule::ComplexIfStatementInStub, Path::new("PYI002.pyi"))] + #[test_case(Rule::CustomTypeVarReturnType, Path::new("PYI019.py"))] + #[test_case(Rule::CustomTypeVarReturnType, Path::new("PYI019.pyi"))] #[test_case(Rule::DocstringInStub, Path::new("PYI021.py"))] #[test_case(Rule::DocstringInStub, Path::new("PYI021.pyi"))] #[test_case(Rule::DuplicateUnionMember, Path::new("PYI016.py"))] #[test_case(Rule::DuplicateUnionMember, Path::new("PYI016.pyi"))] #[test_case(Rule::EllipsisInNonEmptyClassBody, Path::new("PYI013.py"))] #[test_case(Rule::EllipsisInNonEmptyClassBody, Path::new("PYI013.pyi"))] - #[test_case(Rule::NonSelfReturnType, Path::new("PYI034.py"))] - #[test_case(Rule::NonSelfReturnType, Path::new("PYI034.pyi"))] + #[test_case(Rule::FutureAnnotationsInStub, Path::new("PYI044.py"))] + #[test_case(Rule::FutureAnnotationsInStub, Path::new("PYI044.pyi"))] #[test_case(Rule::IterMethodReturnIterable, Path::new("PYI045.py"))] #[test_case(Rule::IterMethodReturnIterable, Path::new("PYI045.pyi"))] #[test_case(Rule::NoReturnArgumentAnnotationInStub, Path::new("PYI050.py"))] #[test_case(Rule::NoReturnArgumentAnnotationInStub, Path::new("PYI050.pyi"))] - #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.py"))] - #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.pyi"))] #[test_case(Rule::NonEmptyStubBody, Path::new("PYI010.py"))] #[test_case(Rule::NonEmptyStubBody, Path::new("PYI010.pyi"))] + #[test_case(Rule::NonSelfReturnType, Path::new("PYI034.py"))] + #[test_case(Rule::NonSelfReturnType, Path::new("PYI034.pyi"))] + #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.py"))] + #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.pyi"))] #[test_case(Rule::PassInClassBody, Path::new("PYI012.py"))] #[test_case(Rule::PassInClassBody, Path::new("PYI012.pyi"))] #[test_case(Rule::PassStatementStubBody, Path::new("PYI009.py"))] #[test_case(Rule::PassStatementStubBody, Path::new("PYI009.pyi"))] + #[test_case(Rule::PatchVersionComparison, Path::new("PYI004.py"))] + #[test_case(Rule::PatchVersionComparison, Path::new("PYI004.pyi"))] #[test_case(Rule::QuotedAnnotationInStub, Path::new("PYI020.py"))] #[test_case(Rule::QuotedAnnotationInStub, Path::new("PYI020.pyi"))] + #[test_case(Rule::RedundantLiteralUnion, Path::new("PYI051.py"))] + #[test_case(Rule::RedundantLiteralUnion, Path::new("PYI051.pyi"))] #[test_case(Rule::RedundantNumericUnion, Path::new("PYI041.py"))] #[test_case(Rule::RedundantNumericUnion, Path::new("PYI041.pyi"))] #[test_case(Rule::SnakeCaseTypeAlias, Path::new("PYI042.py"))] #[test_case(Rule::SnakeCaseTypeAlias, Path::new("PYI042.pyi"))] - #[test_case(Rule::UnassignedSpecialVariableInStub, Path::new("PYI035.py"))] - #[test_case(Rule::UnassignedSpecialVariableInStub, Path::new("PYI035.pyi"))] #[test_case(Rule::StrOrReprDefinedInStub, Path::new("PYI029.py"))] #[test_case(Rule::StrOrReprDefinedInStub, Path::new("PYI029.pyi"))] - #[test_case(Rule::UnnecessaryLiteralUnion, Path::new("PYI030.py"))] - #[test_case(Rule::UnnecessaryLiteralUnion, Path::new("PYI030.pyi"))] + #[test_case(Rule::StringOrBytesTooLong, Path::new("PYI053.py"))] + #[test_case(Rule::StringOrBytesTooLong, Path::new("PYI053.pyi"))] #[test_case(Rule::StubBodyMultipleStatements, Path::new("PYI048.py"))] #[test_case(Rule::StubBodyMultipleStatements, Path::new("PYI048.pyi"))] #[test_case(Rule::TSuffixedTypeAlias, Path::new("PYI043.py"))] #[test_case(Rule::TSuffixedTypeAlias, Path::new("PYI043.pyi"))] - #[test_case(Rule::FutureAnnotationsInStub, Path::new("PYI044.py"))] - #[test_case(Rule::FutureAnnotationsInStub, Path::new("PYI044.pyi"))] - #[test_case(Rule::PatchVersionComparison, Path::new("PYI004.py"))] - #[test_case(Rule::PatchVersionComparison, Path::new("PYI004.pyi"))] + #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.py"))] + #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.pyi"))] #[test_case(Rule::TypeCommentInStub, Path::new("PYI033.py"))] #[test_case(Rule::TypeCommentInStub, Path::new("PYI033.pyi"))] #[test_case(Rule::TypedArgumentDefaultInStub, Path::new("PYI011.py"))] @@ -77,8 +82,12 @@ mod tests { #[test_case(Rule::UnaliasedCollectionsAbcSetImport, Path::new("PYI025.pyi"))] #[test_case(Rule::UnannotatedAssignmentInStub, Path::new("PYI052.py"))] #[test_case(Rule::UnannotatedAssignmentInStub, Path::new("PYI052.pyi"))] - #[test_case(Rule::StringOrBytesTooLong, Path::new("PYI053.py"))] - #[test_case(Rule::StringOrBytesTooLong, Path::new("PYI053.pyi"))] + #[test_case(Rule::UnassignedSpecialVariableInStub, Path::new("PYI035.py"))] + #[test_case(Rule::UnassignedSpecialVariableInStub, Path::new("PYI035.pyi"))] + #[test_case(Rule::UnnecessaryLiteralUnion, Path::new("PYI030.py"))] + #[test_case(Rule::UnnecessaryLiteralUnion, Path::new("PYI030.pyi"))] + #[test_case(Rule::UnnecessaryTypeUnion, Path::new("PYI055.py"))] + #[test_case(Rule::UnnecessaryTypeUnion, Path::new("PYI055.pyi"))] #[test_case(Rule::UnprefixedTypeParam, Path::new("PYI001.py"))] #[test_case(Rule::UnprefixedTypeParam, Path::new("PYI001.pyi"))] #[test_case(Rule::UnrecognizedPlatformCheck, Path::new("PYI007.py"))] @@ -87,20 +96,18 @@ mod tests { #[test_case(Rule::UnrecognizedPlatformName, Path::new("PYI008.pyi"))] #[test_case(Rule::UnrecognizedVersionInfoCheck, Path::new("PYI003.py"))] #[test_case(Rule::UnrecognizedVersionInfoCheck, Path::new("PYI003.pyi"))] - #[test_case(Rule::WrongTupleLengthVersionComparison, Path::new("PYI005.py"))] - #[test_case(Rule::WrongTupleLengthVersionComparison, Path::new("PYI005.pyi"))] - #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.py"))] - #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.pyi"))] #[test_case(Rule::UnsupportedMethodCallOnAll, Path::new("PYI056.py"))] #[test_case(Rule::UnsupportedMethodCallOnAll, Path::new("PYI056.pyi"))] - #[test_case(Rule::UnusedPrivateTypeVar, Path::new("PYI018.py"))] - #[test_case(Rule::UnusedPrivateTypeVar, Path::new("PYI018.pyi"))] #[test_case(Rule::UnusedPrivateProtocol, Path::new("PYI046.py"))] #[test_case(Rule::UnusedPrivateProtocol, Path::new("PYI046.pyi"))] #[test_case(Rule::UnusedPrivateTypeAlias, Path::new("PYI047.py"))] #[test_case(Rule::UnusedPrivateTypeAlias, Path::new("PYI047.pyi"))] + #[test_case(Rule::UnusedPrivateTypeVar, Path::new("PYI018.py"))] + #[test_case(Rule::UnusedPrivateTypeVar, Path::new("PYI018.pyi"))] #[test_case(Rule::UnusedPrivateTypedDict, Path::new("PYI049.py"))] #[test_case(Rule::UnusedPrivateTypedDict, Path::new("PYI049.pyi"))] + #[test_case(Rule::WrongTupleLengthVersionComparison, Path::new("PYI005.py"))] + #[test_case(Rule::WrongTupleLengthVersionComparison, Path::new("PYI005.pyi"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( @@ -110,4 +117,19 @@ mod tests { assert_messages!(snapshot, diagnostics); Ok(()) } + + #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.py"))] + #[test_case(Rule::TypeAliasWithoutAnnotation, Path::new("PYI026.pyi"))] + fn py38(rule_code: Rule, path: &Path) -> Result<()> { + let snapshot = format!("py38_{}_{}", rule_code.noqa_code(), path.to_string_lossy()); + let diagnostics = test_path( + Path::new("flake8_pyi").join(path).as_path(), + &settings::Settings { + target_version: PythonVersion::Py38, + ..settings::Settings::for_rule(rule_code) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs b/crates/ruff/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs index 4ceb91ccc463e..ef1edc80649d4 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arguments, Ranged}; +use ruff_python_ast::{Parameters, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -53,20 +53,20 @@ impl AlwaysAutofixableViolation for AnyEqNeAnnotation { } /// PYI032 -pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arguments) { +pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, parameters: &Parameters) { if !matches!(name, "__eq__" | "__ne__") { return; } - if args.args.len() != 2 { + if parameters.args.len() != 2 { return; } - let Some(annotation) = &args.args[1].def.annotation else { + let Some(annotation) = ¶meters.args[1].parameter.annotation else { return; }; - if !checker.semantic().scope().kind.is_class() { + if !checker.semantic().current_scope().kind.is_class() { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs index 751f2b5c63d41..dd46a4b2bfeb7 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs @@ -75,9 +75,7 @@ pub(crate) fn bad_version_info_comparison(checker: &mut Checker, test: &Expr) { if !checker .semantic() .resolve_call_path(left) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["sys", "version_info"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["sys", "version_info"])) { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/collections_named_tuple.rs b/crates/ruff/src/rules/flake8_pyi/rules/collections_named_tuple.rs index 04049bbfe7e7f..81233fbfb0e39 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/collections_named_tuple.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/collections_named_tuple.rs @@ -53,9 +53,7 @@ pub(crate) fn collections_named_tuple(checker: &mut Checker, expr: &Expr) { if checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["collections", "namedtuple"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["collections", "namedtuple"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_pyi/rules/complex_if_statement_in_stub.rs b/crates/ruff/src/rules/flake8_pyi/rules/complex_if_statement_in_stub.rs index f83bc925df025..fd22dfd8e7c26 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/complex_if_statement_in_stub.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/complex_if_statement_in_stub.rs @@ -67,7 +67,7 @@ pub(crate) fn complex_if_statement_in_stub(checker: &mut Checker, test: &Expr) { if checker .semantic() .resolve_call_path(left) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["sys", "version_info" | "platform"]) }) { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/custom_type_var_return_type.rs b/crates/ruff/src/rules/flake8_pyi/rules/custom_type_var_return_type.rs new file mode 100644 index 0000000000000..3528a580905a6 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/rules/custom_type_var_return_type.rs @@ -0,0 +1,204 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast as ast; +use ruff_python_ast::helpers::map_subscript; +use ruff_python_ast::{Decorator, Expr, Parameters, Ranged, TypeParam, TypeParams}; +use ruff_python_semantic::analyze::visibility::{ + is_abstract, is_classmethod, is_new, is_overload, is_staticmethod, +}; + +use crate::checkers::ast::Checker; + +/// ## What it does +/// Checks for methods that define a custom `TypeVar` for their return type +/// annotation instead of using `typing_extensions.Self`. +/// +/// ## Why is this bad? +/// If certain methods are annotated with a custom `TypeVar` type, and the +/// class is subclassed, type checkers will not be able to infer the correct +/// return type. +/// +/// This check currently applies to instance methods that return `self`, class +/// methods that return an instance of `cls`, and `__new__` methods. +/// +/// ## Example +/// ```python +/// class Foo: +/// def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: +/// ... +/// +/// def foo(self: _S, arg: bytes) -> _S: +/// ... +/// +/// @classmethod +/// def bar(cls: type[_S], arg: int) -> _S: +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// from typing import Self +/// +/// +/// class Foo: +/// def __new__(cls: type[Self], *args: str, **kwargs: int) -> Self: +/// ... +/// +/// def foo(self: Self, arg: bytes) -> Self: +/// ... +/// +/// @classmethod +/// def bar(cls: type[Self], arg: int) -> Self: +/// ... +/// ``` +#[violation] +pub struct CustomTypeVarReturnType { + method_name: String, +} + +impl Violation for CustomTypeVarReturnType { + #[derive_message_formats] + fn message(&self) -> String { + let CustomTypeVarReturnType { method_name } = self; + format!( + "Methods like `{method_name}` should return `typing.Self` instead of a custom `TypeVar`" + ) + } +} + +/// PYI019 +pub(crate) fn custom_type_var_return_type( + checker: &mut Checker, + name: &str, + decorator_list: &[Decorator], + returns: Option<&Expr>, + args: &Parameters, + type_params: Option<&TypeParams>, +) { + // Given, e.g., `def foo(self: _S, arg: bytes) -> _T`, extract `_T`. + let Some(return_annotation) = returns else { + return; + }; + + // Given, e.g., `def foo(self: _S, arg: bytes)`, extract `_S`. + let Some(self_or_cls_annotation) = args + .posonlyargs + .iter() + .chain(args.args.iter()) + .next() + .and_then(|parameter_with_default| parameter_with_default.parameter.annotation.as_ref()) + else { + return; + }; + + if !checker.semantic().current_scope().kind.is_class() { + return; + }; + + // Skip any abstract, static, and overloaded methods. + if is_abstract(decorator_list, checker.semantic()) + || is_overload(decorator_list, checker.semantic()) + || is_staticmethod(decorator_list, checker.semantic()) + { + return; + } + + let uses_custom_var: bool = + if is_classmethod(decorator_list, checker.semantic()) || is_new(name) { + class_method(self_or_cls_annotation, return_annotation, type_params) + } else { + // If not static, or a class method or __new__ we know it is an instance method + instance_method(self_or_cls_annotation, return_annotation, type_params) + }; + + if uses_custom_var { + checker.diagnostics.push(Diagnostic::new( + CustomTypeVarReturnType { + method_name: name.to_string(), + }, + return_annotation.range(), + )); + } +} + +/// Returns `true` if the class method is annotated with a custom `TypeVar` that is likely +/// private. +fn class_method( + cls_annotation: &Expr, + return_annotation: &Expr, + type_params: Option<&TypeParams>, +) -> bool { + let Expr::Subscript(ast::ExprSubscript { slice, value, .. }) = cls_annotation else { + return false; + }; + + let Expr::Name(value) = value.as_ref() else { + return false; + }; + + // Don't error if the first argument is annotated with typing.Type[T]. + // These are edge cases, and it's hard to give good error messages for them. + if value.id != "type" { + return false; + }; + + let Expr::Name(slice) = slice.as_ref() else { + return false; + }; + + let Expr::Name(return_annotation) = map_subscript(return_annotation) else { + return false; + }; + + if slice.id != return_annotation.id { + return false; + } + + is_likely_private_typevar(&slice.id, type_params) +} + +/// Returns `true` if the instance method is annotated with a custom `TypeVar` that is likely +/// private. +fn instance_method( + self_annotation: &Expr, + return_annotation: &Expr, + type_params: Option<&TypeParams>, +) -> bool { + let Expr::Name(ast::ExprName { + id: first_arg_type, .. + }) = self_annotation + else { + return false; + }; + + let Expr::Name(ast::ExprName { + id: return_type, .. + }) = map_subscript(return_annotation) + else { + return false; + }; + + if first_arg_type != return_type { + return false; + } + + is_likely_private_typevar(first_arg_type, type_params) +} + +/// Returns `true` if the type variable is likely private. +fn is_likely_private_typevar(type_var_name: &str, type_params: Option<&TypeParams>) -> bool { + // Ex) `_T` + if type_var_name.starts_with('_') { + return true; + } + // Ex) `class Foo[T]: ...` + type_params.is_some_and(|type_params| { + type_params.iter().any(|type_param| { + if let TypeParam::TypeVar(ast::TypeParamTypeVar { name, .. }) = type_param { + name == type_var_name + } else { + false + } + }) + }) +} diff --git a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs index bba1ef58e281c..74b15ad9c5703 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs @@ -50,12 +50,12 @@ pub(crate) fn duplicate_union_member<'a>(checker: &mut Checker, expr: &'a Expr) // parent without the duplicate. // If the parent node is not a `BinOp` we will not perform a fix - if let Some(Expr::BinOp(ast::ExprBinOp { left, right, .. })) = parent { + if let Some(parent @ Expr::BinOp(ast::ExprBinOp { left, right, .. })) = parent { // Replace the parent with its non-duplicate child. let child = if expr == left.as_ref() { right } else { left }; diagnostic.set_fix(Fix::automatic(Edit::range_replacement( checker.locator().slice(child.range()).to_string(), - parent.unwrap().range(), + parent.range(), ))); } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs index 2462b2ad9857f..6b9d15327c285 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{Expr, ExprConstant, Ranged, Stmt, StmtExpr}; - use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Constant, Expr, ExprConstant, Ranged, Stmt, StmtExpr}; use crate::autofix; use crate::checkers::ast::Checker; @@ -44,11 +43,7 @@ impl Violation for EllipsisInNonEmptyClassBody { } /// PYI013 -pub(crate) fn ellipsis_in_non_empty_class_body( - checker: &mut Checker, - parent: &Stmt, - body: &[Stmt], -) { +pub(crate) fn ellipsis_in_non_empty_class_body(checker: &mut Checker, body: &[Stmt]) { // If the class body contains a single statement, then it's fine for it to be an ellipsis. if body.len() == 1 { return; @@ -59,24 +54,26 @@ pub(crate) fn ellipsis_in_non_empty_class_body( continue; }; - let Expr::Constant(ExprConstant { value, .. }) = value.as_ref() else { - continue; - }; - - if !value.is_ellipsis() { - continue; - } - - let mut diagnostic = Diagnostic::new(EllipsisInNonEmptyClassBody, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = autofix::edits::delete_stmt( - stmt, - Some(parent), - checker.locator(), - checker.indexer(), - ); - diagnostic.set_fix(Fix::automatic(edit).isolate(checker.isolation(Some(parent)))); + if matches!( + value.as_ref(), + Expr::Constant(ExprConstant { + value: Constant::Ellipsis, + .. + }) + ) { + let mut diagnostic = Diagnostic::new(EllipsisInNonEmptyClassBody, stmt.range()); + if checker.patch(diagnostic.kind.rule()) { + let edit = autofix::edits::delete_stmt( + stmt, + Some(stmt), + checker.locator(), + checker.indexer(), + ); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation(Some( + checker.semantic().current_statement_id(), + )))); + } + checker.diagnostics.push(diagnostic); } - checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/exit_annotations.rs b/crates/ruff/src/rules/flake8_pyi/rules/exit_annotations.rs index 185f242002c28..5a183d94d9b92 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/exit_annotations.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/exit_annotations.rs @@ -1,8 +1,8 @@ use std::fmt::{Display, Formatter}; use ruff_python_ast::{ - ArgWithDefault, Arguments, Expr, ExprBinOp, ExprSubscript, ExprTuple, Identifier, Operator, - Ranged, + Expr, ExprBinOp, ExprSubscript, ExprTuple, Identifier, Operator, ParameterWithDefault, + Parameters, Ranged, }; use smallvec::SmallVec; @@ -104,7 +104,7 @@ pub(crate) fn bad_exit_annotation( checker: &mut Checker, is_async: bool, name: &Identifier, - args: &Arguments, + parameters: &Parameters, ) { let func_kind = match name.as_str() { "__exit__" if !is_async => FuncKind::Sync, @@ -112,41 +112,45 @@ pub(crate) fn bad_exit_annotation( _ => return, }; - let positional_args = args + let positional_args = parameters .args .iter() - .chain(args.posonlyargs.iter()) - .collect::>(); + .chain(parameters.posonlyargs.iter()) + .collect::>(); // If there are less than three positional arguments, at least one of them must be a star-arg, // and it must be annotated with `object`. if positional_args.len() < 4 { - check_short_args_list(checker, args, func_kind); + check_short_args_list(checker, parameters, func_kind); } // Every positional argument (beyond the first four) must have a default. - for arg_with_default in positional_args + for parameter in positional_args .iter() .skip(4) - .filter(|arg_with_default| arg_with_default.default.is_none()) + .filter(|parameter| parameter.default.is_none()) { checker.diagnostics.push(Diagnostic::new( BadExitAnnotation { func_kind, error_kind: ErrorKind::ArgsAfterFirstFourMustHaveDefault, }, - arg_with_default.range(), + parameter.range(), )); } // ...as should all keyword-only arguments. - for arg_with_default in args.kwonlyargs.iter().filter(|arg| arg.default.is_none()) { + for parameter in parameters + .kwonlyargs + .iter() + .filter(|arg| arg.default.is_none()) + { checker.diagnostics.push(Diagnostic::new( BadExitAnnotation { func_kind, error_kind: ErrorKind::AllKwargsMustHaveDefault, }, - arg_with_default.range(), + parameter.range(), )); } @@ -155,8 +159,8 @@ pub(crate) fn bad_exit_annotation( /// Determine whether a "short" argument list (i.e., an argument list with less than four elements) /// contains a star-args argument annotated with `object`. If not, report an error. -fn check_short_args_list(checker: &mut Checker, args: &Arguments, func_kind: FuncKind) { - if let Some(varargs) = &args.vararg { +fn check_short_args_list(checker: &mut Checker, parameters: &Parameters, func_kind: FuncKind) { + if let Some(varargs) = ¶meters.vararg { if let Some(annotation) = varargs .annotation .as_ref() @@ -187,7 +191,7 @@ fn check_short_args_list(checker: &mut Checker, args: &Arguments, func_kind: Fun func_kind, error_kind: ErrorKind::MissingArgs, }, - args.range(), + parameters.range(), )); } } @@ -196,7 +200,7 @@ fn check_short_args_list(checker: &mut Checker, args: &Arguments, func_kind: Fun /// annotated correctly. fn check_positional_args( checker: &mut Checker, - positional_args: &[&ArgWithDefault], + positional_args: &[&ParameterWithDefault], kind: FuncKind, ) { // For each argument, define the predicate against which to check the annotation. @@ -209,7 +213,7 @@ fn check_positional_args( ]; for (arg, (error_info, predicate)) in positional_args.iter().skip(1).take(3).zip(validations) { - let Some(annotation) = arg.def.annotation.as_ref() else { + let Some(annotation) = arg.parameter.annotation.as_ref() else { continue; }; @@ -220,7 +224,7 @@ fn check_positional_args( // If there's an annotation that's not `object` or `Unused`, check that the annotated type // matches the predicate. if non_none_annotation_element(annotation, checker.semantic()) - .map_or(false, |elem| predicate(elem, checker.semantic())) + .is_some_and(|elem| predicate(elem, checker.semantic())) { continue; } @@ -238,11 +242,11 @@ fn check_positional_args( /// Return the non-`None` annotation element of a PEP 604-style union or `Optional` annotation. fn non_none_annotation_element<'a>( annotation: &'a Expr, - model: &SemanticModel, + semantic: &SemanticModel, ) -> Option<&'a Expr> { // E.g., `typing.Union` or `typing.Optional` if let Expr::Subscript(ExprSubscript { value, slice, .. }) = annotation { - if model.match_typing_expr(value, "Optional") { + if semantic.match_typing_expr(value, "Optional") { return if is_const_none(slice) { None } else { @@ -250,7 +254,7 @@ fn non_none_annotation_element<'a>( }; } - if !model.match_typing_expr(value, "Union") { + if !semantic.match_typing_expr(value, "Union") { return None; } @@ -293,11 +297,11 @@ fn non_none_annotation_element<'a>( } /// Return `true` if the [`Expr`] is the `object` builtin or the `_typeshed.Unused` type. -fn is_object_or_unused(expr: &Expr, model: &SemanticModel) -> bool { - model +fn is_object_or_unused(expr: &Expr, semantic: &SemanticModel) -> bool { + semantic .resolve_call_path(expr) .as_ref() - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["" | "builtins", "object"] | ["_typeshed", "Unused"] @@ -306,40 +310,34 @@ fn is_object_or_unused(expr: &Expr, model: &SemanticModel) -> bool { } /// Return `true` if the [`Expr`] is `BaseException`. -fn is_base_exception(expr: &Expr, model: &SemanticModel) -> bool { - model +fn is_base_exception(expr: &Expr, semantic: &SemanticModel) -> bool { + semantic .resolve_call_path(expr) .as_ref() - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["" | "builtins", "BaseException"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["" | "builtins", "BaseException"])) } /// Return `true` if the [`Expr`] is the `types.TracebackType` type. -fn is_traceback_type(expr: &Expr, model: &SemanticModel) -> bool { - model +fn is_traceback_type(expr: &Expr, semantic: &SemanticModel) -> bool { + semantic .resolve_call_path(expr) .as_ref() - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["types", "TracebackType"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["types", "TracebackType"])) } /// Return `true` if the [`Expr`] is, e.g., `Type[BaseException]`. -fn is_base_exception_type(expr: &Expr, model: &SemanticModel) -> bool { +fn is_base_exception_type(expr: &Expr, semantic: &SemanticModel) -> bool { let Expr::Subscript(ExprSubscript { value, slice, .. }) = expr else { return false; }; - if model.match_typing_expr(value, "Type") - || model + if semantic.match_typing_expr(value, "Type") + || semantic .resolve_call_path(value) .as_ref() - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["" | "builtins", "type"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["" | "builtins", "type"])) { - is_base_exception(slice, model) + is_base_exception(slice, semantic) } else { false } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/iter_method_return_iterable.rs b/crates/ruff/src/rules/flake8_pyi/rules/iter_method_return_iterable.rs index e45b312d4d3d7..a183b409b408a 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/iter_method_return_iterable.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/iter_method_return_iterable.rs @@ -1,9 +1,9 @@ -use ruff_python_ast as ast; -use ruff_python_ast::{Ranged, Stmt}; +use ruff_python_ast::Ranged; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::Expr; +use ruff_python_ast::helpers::map_subscript; + use ruff_python_semantic::{Definition, Member, MemberKind}; use crate::checkers::ast::Checker; @@ -49,14 +49,14 @@ use crate::checkers::ast::Checker; /// ``` #[violation] pub struct IterMethodReturnIterable { - async_: bool, + is_async: bool, } impl Violation for IterMethodReturnIterable { #[derive_message_formats] fn message(&self) -> String { - let IterMethodReturnIterable { async_ } = self; - if *async_ { + let IterMethodReturnIterable { is_async } = self; + if *is_async { format!("`__aiter__` methods should return an `AsyncIterator`, not an `AsyncIterable`") } else { format!("`__iter__` methods should return an `Iterator`, not an `Iterable`") @@ -67,41 +67,31 @@ impl Violation for IterMethodReturnIterable { /// PYI045 pub(crate) fn iter_method_return_iterable(checker: &mut Checker, definition: &Definition) { let Definition::Member(Member { - kind: MemberKind::Method, - stmt, + kind: MemberKind::Method(function), .. }) = definition else { return; }; - let Stmt::FunctionDef(ast::StmtFunctionDef { name, returns, .. }) = stmt else { - return; - }; - - let Some(returns) = returns else { + let Some(returns) = function.returns.as_ref() else { return; }; - let annotation = if let Expr::Subscript(ast::ExprSubscript { value, .. }) = returns.as_ref() { - // Ex) `Iterable[T]` - value - } else { - // Ex) `Iterable`, `typing.Iterable` - returns - }; - - let async_ = match name.as_str() { + let is_async = match function.name.as_str() { "__iter__" => false, "__aiter__" => true, _ => return, }; + // Support both `Iterable` and `Iterable[T]`. + let annotation = map_subscript(returns); + if checker .semantic() - .resolve_call_path(annotation) - .map_or(false, |call_path| { - if async_ { + .resolve_call_path(map_subscript(annotation)) + .is_some_and(|call_path| { + if is_async { matches!( call_path.as_slice(), ["typing", "AsyncIterable"] | ["collections", "abc", "AsyncIterable"] @@ -115,7 +105,7 @@ pub(crate) fn iter_method_return_iterable(checker: &mut Checker, definition: &De }) { checker.diagnostics.push(Diagnostic::new( - IterMethodReturnIterable { async_ }, + IterMethodReturnIterable { is_async }, returns.range(), )); } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/mod.rs b/crates/ruff/src/rules/flake8_pyi/rules/mod.rs index 6ee3f89e8a74e..3fae99e33d7b2 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/mod.rs @@ -3,6 +3,7 @@ pub(crate) use bad_version_info_comparison::*; pub(crate) use collections_named_tuple::*; pub(crate) use complex_assignment_in_stub::*; pub(crate) use complex_if_statement_in_stub::*; +pub(crate) use custom_type_var_return_type::*; pub(crate) use docstring_in_stubs::*; pub(crate) use duplicate_union_member::*; pub(crate) use ellipsis_in_non_empty_class_body::*; @@ -17,8 +18,10 @@ pub(crate) use pass_in_class_body::*; pub(crate) use pass_statement_stub_body::*; pub(crate) use prefix_type_params::*; pub(crate) use quoted_annotation_in_stub::*; +pub(crate) use redundant_literal_union::*; pub(crate) use redundant_numeric_union::*; pub(crate) use simple_defaults::*; +use std::fmt; pub(crate) use str_or_repr_defined_in_stub::*; pub(crate) use string_or_bytes_too_long::*; pub(crate) use stub_body_multiple_statements::*; @@ -26,6 +29,7 @@ pub(crate) use type_alias_naming::*; pub(crate) use type_comment_in_stub::*; pub(crate) use unaliased_collections_abc_set_import::*; pub(crate) use unnecessary_literal_union::*; +pub(crate) use unnecessary_type_union::*; pub(crate) use unrecognized_platform::*; pub(crate) use unrecognized_version_info::*; pub(crate) use unsupported_method_call_on_all::*; @@ -36,6 +40,7 @@ mod bad_version_info_comparison; mod collections_named_tuple; mod complex_assignment_in_stub; mod complex_if_statement_in_stub; +mod custom_type_var_return_type; mod docstring_in_stubs; mod duplicate_union_member; mod ellipsis_in_non_empty_class_body; @@ -50,6 +55,7 @@ mod pass_in_class_body; mod pass_statement_stub_body; mod prefix_type_params; mod quoted_annotation_in_stub; +mod redundant_literal_union; mod redundant_numeric_union; mod simple_defaults; mod str_or_repr_defined_in_stub; @@ -59,7 +65,31 @@ mod type_alias_naming; mod type_comment_in_stub; mod unaliased_collections_abc_set_import; mod unnecessary_literal_union; +mod unnecessary_type_union; mod unrecognized_platform; mod unrecognized_version_info; mod unsupported_method_call_on_all; mod unused_private_type_definition; + +// TODO(charlie): Replace this with a common utility for selecting the appropriate source +// module for a given `typing` member. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum TypingModule { + Typing, + TypingExtensions, +} + +impl TypingModule { + fn as_str(self) -> &'static str { + match self { + TypingModule::Typing => "typing", + TypingModule::TypingExtensions => "typing_extensions", + } + } +} + +impl fmt::Display for TypingModule { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(self.as_str()) + } +} diff --git a/crates/ruff/src/rules/flake8_pyi/rules/no_return_argument_annotation.rs b/crates/ruff/src/rules/flake8_pyi/rules/no_return_argument_annotation.rs index e4cafdbbcdb05..e95b6c53047a5 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/no_return_argument_annotation.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/no_return_argument_annotation.rs @@ -4,7 +4,7 @@ use ruff_python_ast::Ranged; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::Arguments; +use ruff_python_ast::Parameters; use crate::checkers::ast::Checker; use crate::settings::types::PythonVersion::Py311; @@ -47,13 +47,13 @@ impl Violation for NoReturnArgumentAnnotationInStub { } /// PYI050 -pub(crate) fn no_return_argument_annotation(checker: &mut Checker, args: &Arguments) { - for annotation in args +pub(crate) fn no_return_argument_annotation(checker: &mut Checker, parameters: &Parameters) { + for annotation in parameters .posonlyargs .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) - .filter_map(|arg| arg.def.annotation.as_ref()) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .filter_map(|arg| arg.parameter.annotation.as_ref()) { if checker.semantic().match_typing_expr(annotation, "NoReturn") { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs index b2bea54acba8f..ea165f358cd0f 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/non_empty_stub_body.rs @@ -22,10 +22,7 @@ impl AlwaysAutofixableViolation for NonEmptyStubBody { /// PYI010 pub(crate) fn non_empty_stub_body(checker: &mut Checker, body: &[Stmt]) { - if body.len() != 1 { - return; - } - if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body[0] { + if let [Stmt::Expr(ast::StmtExpr { value, range: _ })] = body { if let Expr::Constant(ast::ExprConstant { value, .. }) = value.as_ref() { if matches!(value, Constant::Ellipsis | Constant::Str(_)) { return; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/non_self_return_type.rs b/crates/ruff/src/rules/flake8_pyi/rules/non_self_return_type.rs index afa50883424fe..0f251297cb6f1 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/non_self_return_type.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/non_self_return_type.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, Parameters, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -113,17 +113,17 @@ impl Violation for NonSelfReturnType { pub(crate) fn non_self_return_type( checker: &mut Checker, stmt: &Stmt, + is_async: bool, name: &str, decorator_list: &[Decorator], returns: Option<&Expr>, - args: &Arguments, - async_: bool, + parameters: &Parameters, ) { - let ScopeKind::Class(class_def) = checker.semantic().scope().kind else { + let ScopeKind::Class(class_def) = checker.semantic().current_scope().kind else { return; }; - if args.args.is_empty() && args.posonlyargs.is_empty() { + if parameters.args.is_empty() && parameters.posonlyargs.is_empty() { return; } @@ -138,7 +138,7 @@ pub(crate) fn non_self_return_type( return; } - if async_ { + if is_async { if name == "__aenter__" && is_name(returns, &class_def.name) && !is_final(&class_def.decorator_list, checker.semantic()) @@ -186,7 +186,7 @@ pub(crate) fn non_self_return_type( match name { "__iter__" => { if is_iterable(returns, checker.semantic()) - && is_iterator(&class_def.bases, checker.semantic()) + && is_iterator(class_def.arguments.as_deref(), checker.semantic()) { checker.diagnostics.push(Diagnostic::new( NonSelfReturnType { @@ -199,7 +199,7 @@ pub(crate) fn non_self_return_type( } "__aiter__" => { if is_async_iterable(returns, checker.semantic()) - && is_async_iterator(&class_def.bases, checker.semantic()) + && is_async_iterator(class_def.arguments.as_deref(), checker.semantic()) { checker.diagnostics.push(Diagnostic::new( NonSelfReturnType { @@ -248,11 +248,14 @@ fn is_self(expr: &Expr, semantic: &SemanticModel) -> bool { } /// Return `true` if the given class extends `collections.abc.Iterator`. -fn is_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool { +fn is_iterator(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool { + let Some(Arguments { args: bases, .. }) = arguments else { + return false; + }; bases.iter().any(|expr| { semantic .resolve_call_path(map_subscript(expr)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["typing", "Iterator"] | ["collections", "abc", "Iterator"] @@ -265,7 +268,7 @@ fn is_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool { fn is_iterable(expr: &Expr, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(map_subscript(expr)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["typing", "Iterable" | "Iterator"] @@ -275,11 +278,14 @@ fn is_iterable(expr: &Expr, semantic: &SemanticModel) -> bool { } /// Return `true` if the given class extends `collections.abc.AsyncIterator`. -fn is_async_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool { +fn is_async_iterator(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool { + let Some(Arguments { args: bases, .. }) = arguments else { + return false; + }; bases.iter().any(|expr| { semantic .resolve_call_path(map_subscript(expr)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["typing", "AsyncIterator"] | ["collections", "abc", "AsyncIterator"] @@ -292,7 +298,7 @@ fn is_async_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool { fn is_async_iterable(expr: &Expr, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(map_subscript(expr)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["typing", "AsyncIterable" | "AsyncIterator"] diff --git a/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs index a16d7437f86f9..f5d071132e568 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/pass_in_class_body.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{Ranged, Stmt}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Ranged}; use crate::autofix; use crate::checkers::ast::Checker; @@ -22,26 +21,24 @@ impl AlwaysAutofixableViolation for PassInClassBody { } /// PYI012 -pub(crate) fn pass_in_class_body(checker: &mut Checker, parent: &Stmt, body: &[Stmt]) { +pub(crate) fn pass_in_class_body(checker: &mut Checker, class_def: &ast::StmtClassDef) { // `pass` is required in these situations (or handled by `pass_statement_stub_body`). - if body.len() < 2 { + if class_def.body.len() < 2 { return; } - for stmt in body { + for stmt in &class_def.body { if !stmt.is_pass_stmt() { continue; } let mut diagnostic = Diagnostic::new(PassInClassBody, stmt.range()); if checker.patch(diagnostic.kind.rule()) { - let edit = autofix::edits::delete_stmt( - stmt, - Some(parent), - checker.locator(), - checker.indexer(), - ); - diagnostic.set_fix(Fix::automatic(edit).isolate(checker.isolation(Some(parent)))); + let edit = + autofix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation(Some( + checker.semantic().current_statement_id(), + )))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs b/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs index 769cfcfcf9bd5..b9d957b819e0c 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{Ranged, Stmt}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::registry::Rule; @@ -22,15 +21,15 @@ impl AlwaysAutofixableViolation for PassStatementStubBody { /// PYI009 pub(crate) fn pass_statement_stub_body(checker: &mut Checker, body: &[Stmt]) { - if body.len() != 1 { + let [stmt] = body else { return; - } - if body[0].is_pass_stmt() { - let mut diagnostic = Diagnostic::new(PassStatementStubBody, body[0].range()); + }; + if stmt.is_pass_stmt() { + let mut diagnostic = Diagnostic::new(PassStatementStubBody, stmt.range()); if checker.patch(Rule::PassStatementStubBody) { diagnostic.set_fix(Fix::automatic(Edit::range_replacement( format!("..."), - body[0].range(), + stmt.range(), ))); }; checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs new file mode 100644 index 0000000000000..b1c112c0f9f9f --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs @@ -0,0 +1,155 @@ +use rustc_hash::FxHashSet; +use std::fmt; + +use ast::{Constant, Ranged}; +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr}; +use ruff_python_semantic::SemanticModel; + +use crate::{checkers::ast::Checker, rules::flake8_pyi::helpers::traverse_union}; + +/// ## What it does +/// Checks for the presence of redundant `Literal` types and builtin super +/// types in an union. +/// +/// ## Why is this bad? +/// The use of `Literal` types in a union with the builtin super type of one of +/// its literal members is redundant, as the super type is strictly more +/// general than the `Literal` type. +/// +/// For example, `Literal["A"] | str` is equivalent to `str`, and +/// `Literal[1] | int` is equivalent to `int`, as `str` and `int` are the super +/// types of `"A"` and `1` respectively. +/// +/// ## Example +/// ```python +/// from typing import Literal +/// +/// A: Literal["A"] | str +/// ``` +/// +/// Use instead: +/// ```python +/// from typing import Literal +/// +/// A: Literal["A"] +/// ``` +#[violation] +pub struct RedundantLiteralUnion { + literal: String, + builtin_type: ExprType, +} + +impl Violation for RedundantLiteralUnion { + #[derive_message_formats] + fn message(&self) -> String { + let RedundantLiteralUnion { + literal, + builtin_type, + } = self; + format!("`Literal[{literal}]` is redundant in a union with `{builtin_type}`",) + } +} + +/// PYI051 +pub(crate) fn redundant_literal_union<'a>(checker: &mut Checker, union: &'a Expr) { + let mut literal_exprs = Vec::new(); + let mut builtin_types_in_union = FxHashSet::default(); + + // Adds a member to `literal_exprs` for each value in a `Literal`, and any builtin types + // to `builtin_types_in_union`. + let mut func = |expr: &'a Expr, _| { + if let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr { + if checker.semantic().match_typing_expr(value, "Literal") { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() { + literal_exprs.extend(elts.iter()); + } else { + literal_exprs.push(slice); + } + } + return; + } + + let Some(builtin_type) = match_builtin_type(expr, checker.semantic()) else { + return; + }; + builtin_types_in_union.insert(builtin_type); + }; + + traverse_union(&mut func, checker.semantic(), union, None); + + for literal_expr in literal_exprs { + let Some(constant_type) = match_constant_type(literal_expr) else { + continue; + }; + + if builtin_types_in_union.contains(&constant_type) { + checker.diagnostics.push(Diagnostic::new( + RedundantLiteralUnion { + literal: checker.locator().slice(literal_expr.range()).to_string(), + builtin_type: constant_type, + }, + literal_expr.range(), + )); + } + } +} + +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +enum ExprType { + Int, + Str, + Bool, + Float, + Bytes, + Complex, +} + +impl fmt::Display for ExprType { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Int => fmt.write_str("int"), + Self::Str => fmt.write_str("str"), + Self::Bool => fmt.write_str("bool"), + Self::Float => fmt.write_str("float"), + Self::Bytes => fmt.write_str("bytes"), + Self::Complex => fmt.write_str("complex"), + } + } +} + +/// Return the [`ExprType`] of an [`Expr]` if it is a builtin type (e.g. `int`, `bool`, `float`, +/// `str`, `bytes`, or `complex`). +fn match_builtin_type(expr: &Expr, semantic: &SemanticModel) -> Option { + let name = expr.as_name_expr()?; + let result = match name.id.as_str() { + "int" => ExprType::Int, + "bool" => ExprType::Bool, + "str" => ExprType::Str, + "float" => ExprType::Float, + "bytes" => ExprType::Bytes, + "complex" => ExprType::Complex, + _ => return None, + }; + if !semantic.is_builtin(name.id.as_str()) { + return None; + } + Some(result) +} + +/// Return the [`ExprType`] of an [`Expr]` if it is a constant (e.g., an `int`, like `1`, or a +/// `bool`, like `True`). +fn match_constant_type(expr: &Expr) -> Option { + let constant = expr.as_constant_expr()?; + let result = match constant.value { + Constant::Bool(_) => ExprType::Bool, + Constant::Str(_) => ExprType::Str, + Constant::Bytes(_) => ExprType::Bytes, + Constant::Int(_) => ExprType::Int, + Constant::Float(_) => ExprType::Float, + Constant::Complex { .. } => ExprType::Complex, + _ => return None, + }; + Some(result) +} diff --git a/crates/ruff/src/rules/flake8_pyi/rules/redundant_numeric_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/redundant_numeric_union.rs index d16f7928a5968..e9e3a7855e9ce 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/redundant_numeric_union.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/redundant_numeric_union.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arguments, Expr, Ranged}; +use ruff_python_ast::{Expr, Parameters, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -53,13 +53,13 @@ impl Violation for RedundantNumericUnion { } /// PYI041 -pub(crate) fn redundant_numeric_union(checker: &mut Checker, args: &Arguments) { - for annotation in args +pub(crate) fn redundant_numeric_union(checker: &mut Checker, parameters: &Parameters) { + for annotation in parameters .args .iter() - .chain(args.posonlyargs.iter()) - .chain(args.kwonlyargs.iter()) - .filter_map(|arg| arg.def.annotation.as_ref()) + .chain(parameters.posonlyargs.iter()) + .chain(parameters.kwonlyargs.iter()) + .filter_map(|arg| arg.parameter.annotation.as_ref()) { check_annotation(checker, annotation); } @@ -67,10 +67,10 @@ pub(crate) fn redundant_numeric_union(checker: &mut Checker, args: &Arguments) { // If annotations on `args` or `kwargs` are flagged by this rule, the annotations themselves // are not accurate, but check them anyway. It's possible that flagging them will help the user // realize they're incorrect. - for annotation in args + for annotation in parameters .vararg .iter() - .chain(args.kwarg.iter()) + .chain(parameters.kwarg.iter()) .filter_map(|arg| arg.annotation.as_ref()) { check_annotation(checker, annotation); diff --git a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs index c63143dc0b184..355930bfa7311 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -1,16 +1,18 @@ -use ruff_python_ast::{ - self as ast, ArgWithDefault, Arguments, Constant, Expr, Operator, Ranged, Stmt, UnaryOp, -}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::CallPath; +use ruff_python_ast::{ + self as ast, Arguments, Constant, Expr, Operator, ParameterWithDefault, Parameters, Ranged, + Stmt, UnaryOp, +}; use ruff_python_semantic::{ScopeKind, SemanticModel}; use ruff_source_file::Locator; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; use crate::registry::AsRule; +use crate::rules::flake8_pyi::rules::TypingModule; +use crate::settings::types::PythonVersion; #[violation] pub struct TypedArgumentDefaultInStub; @@ -123,6 +125,7 @@ impl Violation for UnassignedSpecialVariableInStub { /// ``` #[violation] pub struct TypeAliasWithoutAnnotation { + module: TypingModule, name: String, value: String, } @@ -130,12 +133,16 @@ pub struct TypeAliasWithoutAnnotation { impl AlwaysAutofixableViolation for TypeAliasWithoutAnnotation { #[derive_message_formats] fn message(&self) -> String { - let TypeAliasWithoutAnnotation { name, value } = self; - format!("Use `typing.TypeAlias` for type alias, e.g., `{name}: typing.TypeAlias = {value}`") + let TypeAliasWithoutAnnotation { + module, + name, + value, + } = self; + format!("Use `{module}.TypeAlias` for type alias, e.g., `{name}: TypeAlias = {value}`") } fn autofix_title(&self) -> String { - "Add `typing.TypeAlias` annotation".to_string() + "Add `TypeAlias` annotation".to_string() } } @@ -194,7 +201,7 @@ fn is_valid_default_value_with_annotation( return allow_container && keys.len() <= 10 && keys.iter().zip(values).all(|(k, v)| { - k.as_ref().map_or(false, |k| { + k.as_ref().is_some_and(|k| { is_valid_default_value_with_annotation(k, false, locator, semantic) }) && is_valid_default_value_with_annotation(v, false, locator, semantic) }); @@ -215,7 +222,7 @@ fn is_valid_default_value_with_annotation( if semantic .resolve_call_path(operand) .as_ref() - .map_or(false, is_allowed_negated_math_attribute) + .is_some_and(is_allowed_negated_math_attribute) { return true; } @@ -264,7 +271,7 @@ fn is_valid_default_value_with_annotation( if semantic .resolve_call_path(default) .as_ref() - .map_or(false, is_allowed_math_attribute) + .is_some_and(is_allowed_math_attribute) { return true; } @@ -332,7 +339,7 @@ fn is_type_var_like_call(expr: &Expr, semantic: &SemanticModel) -> bool { let Expr::Call(ast::ExprCall { func, .. }) = expr else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { + semantic.resolve_call_path(func).is_some_and(|call_path| { matches!( call_path.as_slice(), [ @@ -348,8 +355,8 @@ fn is_type_var_like_call(expr: &Expr, semantic: &SemanticModel) -> bool { fn is_special_assignment(target: &Expr, semantic: &SemanticModel) -> bool { if let Expr::Name(ast::ExprName { id, .. }) = target { match id.as_str() { - "__all__" => semantic.scope().kind.is_module(), - "__match_args__" | "__slots__" => semantic.scope().kind.is_class(), + "__all__" => semantic.current_scope().kind.is_module(), + "__match_args__" | "__slots__" => semantic.current_scope().kind.is_class(), _ => false, } } else { @@ -368,9 +375,12 @@ fn is_final_assignment(annotation: &Expr, value: &Expr, semantic: &SemanticModel } /// Returns `true` if the a class is an enum, based on its base classes. -fn is_enum(bases: &[Expr], semantic: &SemanticModel) -> bool { +fn is_enum(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool { + let Some(Arguments { args: bases, .. }) = arguments else { + return false; + }; return bases.iter().any(|expr| { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { matches!( call_path.as_slice(), [ @@ -400,21 +410,21 @@ fn is_annotatable_type_alias(value: &Expr, semantic: &SemanticModel) -> bool { } /// PYI011 -pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, arguments: &Arguments) { - for ArgWithDefault { - def, +pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, parameters: &Parameters) { + for ParameterWithDefault { + parameter, default, range: _, - } in arguments + } in parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) { let Some(default) = default else { continue; }; - if def.annotation.is_some() { + if parameter.annotation.is_some() { if !is_valid_default_value_with_annotation( default, true, @@ -437,21 +447,21 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, arguments: & } /// PYI014 -pub(crate) fn argument_simple_defaults(checker: &mut Checker, arguments: &Arguments) { - for ArgWithDefault { - def, +pub(crate) fn argument_simple_defaults(checker: &mut Checker, parameters: &Parameters) { + for ParameterWithDefault { + parameter, default, range: _, - } in arguments + } in parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) { let Some(default) = default else { continue; }; - if def.annotation.is_none() { + if parameter.annotation.is_none() { if !is_valid_default_value_with_annotation( default, true, @@ -565,8 +575,10 @@ pub(crate) fn unannotated_assignment_in_stub( return; } - if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = checker.semantic().scope().kind { - if is_enum(bases, checker.semantic()) { + if let ScopeKind::Class(ast::StmtClassDef { arguments, .. }) = + checker.semantic().current_scope().kind + { + if is_enum(arguments.as_deref(), checker.semantic()) { return; } } @@ -600,7 +612,7 @@ pub(crate) fn unassigned_special_variable_in_stub( )); } -/// PIY026 +/// PYI026 pub(crate) fn type_alias_without_annotation(checker: &mut Checker, value: &Expr, targets: &[Expr]) { let [target] = targets else { return; @@ -614,8 +626,15 @@ pub(crate) fn type_alias_without_annotation(checker: &mut Checker, value: &Expr, return; } + let module = if checker.settings.target_version >= PythonVersion::Py310 { + TypingModule::Typing + } else { + TypingModule::TypingExtensions + }; + let mut diagnostic = Diagnostic::new( TypeAliasWithoutAnnotation { + module, name: id.to_string(), value: checker.generator().expr(value), }, @@ -624,7 +643,7 @@ pub(crate) fn type_alias_without_annotation(checker: &mut Checker, value: &Expr, if checker.patch(diagnostic.kind.rule()) { diagnostic.try_set_fix(|| { let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("typing", "TypeAlias"), + &ImportRequest::import(module.as_str(), "TypeAlias"), target.start(), checker.semantic(), )?; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs b/crates/ruff/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs index 58035705f43e0..6676c9009e213 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs @@ -48,7 +48,7 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) { name, decorator_list, returns, - args, + parameters, .. }) = stmt else { @@ -63,13 +63,15 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) { return; } - if !checker.semantic().scope().kind.is_class() { + if !checker.semantic().current_scope().kind.is_class() { return; } // It is a violation only if the method signature matches that of `object.__str__` // or `object.__repr__` exactly and the method is not decorated as abstract. - if !args.kwonlyargs.is_empty() || (args.args.len() + args.posonlyargs.len()) > 1 { + if !parameters.kwonlyargs.is_empty() + || (parameters.args.len() + parameters.posonlyargs.len()) > 1 + { return; } @@ -94,12 +96,12 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) { stmt.identifier(), ); if checker.patch(diagnostic.kind.rule()) { - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix( - Fix::automatic(edit).isolate(checker.isolation(checker.semantic().stmt_parent())), - ); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs b/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs index 4fd45acd7ffe3..c66ecf894f5e6 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs @@ -43,7 +43,7 @@ impl AlwaysAutofixableViolation for StringOrBytesTooLong { /// PYI053 pub(crate) fn string_or_bytes_too_long(checker: &mut Checker, expr: &Expr) { // Ignore docstrings. - if is_docstring_stmt(checker.semantic().stmt()) { + if is_docstring_stmt(checker.semantic().current_statement()) { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs b/crates/ruff/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs index 6afd64b25b3e7..a272e18385ab6 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs @@ -1,6 +1,8 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Binding, BindingKind, FromImport}; +use ruff_python_ast::Ranged; +use ruff_python_semantic::Imported; +use ruff_python_semantic::{Binding, BindingKind}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -50,10 +52,10 @@ pub(crate) fn unaliased_collections_abc_set_import( checker: &Checker, binding: &Binding, ) -> Option { - let BindingKind::FromImport(FromImport { qualified_name }) = &binding.kind else { + let BindingKind::FromImport(import) = &binding.kind else { return None; }; - if qualified_name.as_str() != "collections.abc.Set" { + if !matches!(import.call_path(), ["collections", "abc", "Set"]) { return None; } @@ -62,7 +64,7 @@ pub(crate) fn unaliased_collections_abc_set_import( return None; } - let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range); + let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range()); if checker.patch(diagnostic.kind.rule()) { if checker.semantic().is_available("AbstractSet") { diagnostic.try_set_fix(|| { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs new file mode 100644 index 0000000000000..8c0cac5c9763e --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs @@ -0,0 +1,87 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Expr, Ranged}; + +use crate::{checkers::ast::Checker, rules::flake8_pyi::helpers::traverse_union}; + +/// ## What it does +/// Checks for the presence of multiple `type`s in a union. +/// +/// ## Why is this bad? +/// The `type` built-in function accepts unions, and it is +/// clearer to explicitly specify them as a single `type`. +/// +/// ## Example +/// ```python +/// field: type[int] | type[float] +/// ``` +/// +/// Use instead: +/// ```python +/// field: type[int | float] +/// ``` +#[violation] +pub struct UnnecessaryTypeUnion { + members: Vec, + is_pep604_union: bool, +} + +impl Violation for UnnecessaryTypeUnion { + #[derive_message_formats] + fn message(&self) -> String { + let union_str = if self.is_pep604_union { + format!("{}", self.members.join(" | ")) + } else { + format!("Union[{}]", self.members.join(", ")) + }; + + format!( + "Multiple `type` members in a union. Combine them into one, e.g., `type[{union_str}]`." + ) + } +} + +/// PYI055 +pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr) { + // The `|` operator isn't always safe to allow to runtime-evaluated annotations. + if checker.semantic().execution_context().is_runtime() { + return; + } + + let mut type_exprs = Vec::new(); + + // Check if `union` is a PEP604 union (e.g. `float | int`) or a `typing.Union[float, int]` + let is_pep604_union = !union.as_subscript_expr().is_some_and(|subscript| { + checker + .semantic() + .match_typing_expr(&subscript.value, "Union") + }); + + let mut collect_type_exprs = |expr: &'a Expr, _| { + let Some(subscript) = expr.as_subscript_expr() else { + return; + }; + if checker + .semantic() + .resolve_call_path(subscript.value.as_ref()) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["" | "builtins", "type"])) + { + type_exprs.push(&subscript.slice); + } + }; + + traverse_union(&mut collect_type_exprs, checker.semantic(), union, None); + + if type_exprs.len() > 1 { + checker.diagnostics.push(Diagnostic::new( + UnnecessaryTypeUnion { + members: type_exprs + .into_iter() + .map(|type_expr| checker.locator().slice(type_expr.range()).to_string()) + .collect(), + is_pep604_union, + }, + union.range(), + )); + } +} diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs index d3381dbeb31da..75d48b7326b31 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs @@ -107,9 +107,7 @@ pub(crate) fn unrecognized_platform(checker: &mut Checker, test: &Expr) { if !checker .semantic() .resolve_call_path(left) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["sys", "platform"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["sys", "platform"])) { return; } @@ -125,7 +123,7 @@ pub(crate) fn unrecognized_platform(checker: &mut Checker, test: &Expr) { } if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = right { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_version_info.rs b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_version_info.rs index 53e1e90e55d43..3f4c07209b131 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_version_info.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_version_info.rs @@ -138,9 +138,7 @@ pub(crate) fn unrecognized_version_info(checker: &mut Checker, test: &Expr) { if !checker .semantic() .resolve_call_path(map_subscript(left)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["sys", "version_info"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["sys", "version_info"])) { return; } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs b/crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs index 2a80276d7265a..3a306d064923e 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs @@ -1,6 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use ruff_python_semantic::Scope; use crate::checkers::ast::Checker; @@ -173,7 +173,8 @@ pub(crate) fn unused_private_type_var( let Some(source) = binding.source else { continue; }; - let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = checker.semantic().stmts[source] + let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = + checker.semantic().statement(source) else { continue; }; @@ -191,7 +192,7 @@ pub(crate) fn unused_private_type_var( UnusedPrivateTypeVar { name: id.to_string(), }, - binding.range, + binding.range(), )); } } @@ -216,13 +217,13 @@ pub(crate) fn unused_private_protocol( let Some(source) = binding.source else { continue; }; - let Stmt::ClassDef(ast::StmtClassDef { name, bases, .. }) = - checker.semantic().stmts[source] - else { + + let Stmt::ClassDef(class_def) = checker.semantic().statement(source) else { continue; }; - if !bases + if !class_def + .bases() .iter() .any(|base| checker.semantic().match_typing_expr(base, "Protocol")) { @@ -231,9 +232,9 @@ pub(crate) fn unused_private_protocol( diagnostics.push(Diagnostic::new( UnusedPrivateProtocol { - name: name.to_string(), + name: class_def.name.to_string(), }, - binding.range, + binding.range(), )); } } @@ -260,7 +261,7 @@ pub(crate) fn unused_private_type_alias( }; let Stmt::AnnAssign(ast::StmtAnnAssign { target, annotation, .. - }) = checker.semantic().stmts[source] + }) = checker.semantic().statement(source) else { continue; }; @@ -279,7 +280,7 @@ pub(crate) fn unused_private_type_alias( UnusedPrivateTypeAlias { name: id.to_string(), }, - binding.range, + binding.range(), )); } } @@ -304,13 +305,12 @@ pub(crate) fn unused_private_typed_dict( let Some(source) = binding.source else { continue; }; - let Stmt::ClassDef(ast::StmtClassDef { name, bases, .. }) = - checker.semantic().stmts[source] - else { + let Stmt::ClassDef(class_def) = checker.semantic().statement(source) else { continue; }; - if !bases + if !class_def + .bases() .iter() .any(|base| checker.semantic().match_typing_expr(base, "TypedDict")) { @@ -319,9 +319,9 @@ pub(crate) fn unused_private_typed_dict( diagnostics.push(Diagnostic::new( UnusedPrivateTypedDict { - name: name.to_string(), + name: class_def.name.to_string(), }, - binding.range, + binding.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI013_PYI013.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI013_PYI013.py.snap index d1aa2e9116558..7e0954fb1cf64 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI013_PYI013.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI013_PYI013.py.snap @@ -1,4 +1,149 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI013.py:3:5: PYI013 [*] Non-empty class body must not contain `...` + | +1 | class OneAttributeClass: +2 | value: int +3 | ... + | ^^^ PYI013 + | + = help: Remove unnecessary `...` + +ℹ Fix +1 1 | class OneAttributeClass: +2 2 | value: int +3 |- ... +4 3 | +5 4 | +6 5 | class OneAttributeClass2: + +PYI013.py:7:5: PYI013 [*] Non-empty class body must not contain `...` + | +6 | class OneAttributeClass2: +7 | ... + | ^^^ PYI013 +8 | value: int + | + = help: Remove unnecessary `...` + +ℹ Fix +4 4 | +5 5 | +6 6 | class OneAttributeClass2: +7 |- ... +8 7 | value: int +9 8 | +10 9 | + +PYI013.py:12:5: PYI013 [*] Non-empty class body must not contain `...` + | +11 | class TwoEllipsesClass: +12 | ... + | ^^^ PYI013 +13 | ... + | + = help: Remove unnecessary `...` + +ℹ Fix +10 10 | +11 11 | class TwoEllipsesClass: +12 12 | ... +13 |- ... +14 13 | +15 14 | +16 15 | class DocstringClass: + +PYI013.py:13:5: PYI013 [*] Non-empty class body must not contain `...` + | +11 | class TwoEllipsesClass: +12 | ... +13 | ... + | ^^^ PYI013 + | + = help: Remove unnecessary `...` + +ℹ Fix +10 10 | +11 11 | class TwoEllipsesClass: +12 12 | ... +13 |- ... +14 13 | +15 14 | +16 15 | class DocstringClass: + +PYI013.py:21:5: PYI013 [*] Non-empty class body must not contain `...` + | +19 | """ +20 | +21 | ... + | ^^^ PYI013 + | + = help: Remove unnecessary `...` + +ℹ Fix +18 18 | My body only contains an ellipsis. +19 19 | """ +20 20 | +21 |- ... +22 21 | +23 22 | +24 23 | class NonEmptyChild(Exception): + +PYI013.py:26:5: PYI013 [*] Non-empty class body must not contain `...` + | +24 | class NonEmptyChild(Exception): +25 | value: int +26 | ... + | ^^^ PYI013 + | + = help: Remove unnecessary `...` + +ℹ Fix +23 23 | +24 24 | class NonEmptyChild(Exception): +25 25 | value: int +26 |- ... +27 26 | +28 27 | +29 28 | class NonEmptyChild2(Exception): + +PYI013.py:30:5: PYI013 [*] Non-empty class body must not contain `...` + | +29 | class NonEmptyChild2(Exception): +30 | ... + | ^^^ PYI013 +31 | value: int + | + = help: Remove unnecessary `...` + +ℹ Fix +27 27 | +28 28 | +29 29 | class NonEmptyChild2(Exception): +30 |- ... +31 30 | value: int +32 31 | +33 32 | + +PYI013.py:36:5: PYI013 [*] Non-empty class body must not contain `...` + | +34 | class NonEmptyWithInit: +35 | value: int +36 | ... + | ^^^ PYI013 +37 | +38 | def __init__(): + | + = help: Remove unnecessary `...` + +ℹ Fix +33 33 | +34 34 | class NonEmptyWithInit: +35 35 | value: int +36 |- ... +37 36 | +38 37 | def __init__(): +39 38 | pass + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.py.snap index d1aa2e9116558..abc1d3226a55e 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.py.snap @@ -1,4 +1,543 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI016.py:7:15: PYI016 [*] Duplicate union member `str` + | +6 | # Should emit for duplicate field types. +7 | field2: str | str # PYI016: Duplicate union member `str` + | ^^^ PYI016 +8 | +9 | # Should emit for union types in arguments. + | + = help: Remove duplicate union member `str` + +ℹ Fix +4 4 | field1: str +5 5 | +6 6 | # Should emit for duplicate field types. +7 |-field2: str | str # PYI016: Duplicate union member `str` + 7 |+field2: str # PYI016: Duplicate union member `str` +8 8 | +9 9 | # Should emit for union types in arguments. +10 10 | def func1(arg1: int | int): # PYI016: Duplicate union member `int` + +PYI016.py:10:23: PYI016 [*] Duplicate union member `int` + | + 9 | # Should emit for union types in arguments. +10 | def func1(arg1: int | int): # PYI016: Duplicate union member `int` + | ^^^ PYI016 +11 | print(arg1) + | + = help: Remove duplicate union member `int` + +ℹ Fix +7 7 | field2: str | str # PYI016: Duplicate union member `str` +8 8 | +9 9 | # Should emit for union types in arguments. +10 |-def func1(arg1: int | int): # PYI016: Duplicate union member `int` + 10 |+def func1(arg1: int): # PYI016: Duplicate union member `int` +11 11 | print(arg1) +12 12 | +13 13 | # Should emit for unions in return types. + +PYI016.py:14:22: PYI016 [*] Duplicate union member `str` + | +13 | # Should emit for unions in return types. +14 | def func2() -> str | str: # PYI016: Duplicate union member `str` + | ^^^ PYI016 +15 | return "my string" + | + = help: Remove duplicate union member `str` + +ℹ Fix +11 11 | print(arg1) +12 12 | +13 13 | # Should emit for unions in return types. +14 |-def func2() -> str | str: # PYI016: Duplicate union member `str` + 14 |+def func2() -> str: # PYI016: Duplicate union member `str` +15 15 | return "my string" +16 16 | +17 17 | # Should emit in longer unions, even if not directly adjacent. + +PYI016.py:18:15: PYI016 [*] Duplicate union member `str` + | +17 | # Should emit in longer unions, even if not directly adjacent. +18 | field3: str | str | int # PYI016: Duplicate union member `str` + | ^^^ PYI016 +19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 | field5: str | int | str # PYI016: Duplicate union member `str` + | + = help: Remove duplicate union member `str` + +ℹ Fix +15 15 | return "my string" +16 16 | +17 17 | # Should emit in longer unions, even if not directly adjacent. +18 |-field3: str | str | int # PYI016: Duplicate union member `str` + 18 |+field3: str | int # PYI016: Duplicate union member `str` +19 19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 20 | field5: str | int | str # PYI016: Duplicate union member `str` +21 21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` + +PYI016.py:19:15: PYI016 [*] Duplicate union member `int` + | +17 | # Should emit in longer unions, even if not directly adjacent. +18 | field3: str | str | int # PYI016: Duplicate union member `str` +19 | field4: int | int | str # PYI016: Duplicate union member `int` + | ^^^ PYI016 +20 | field5: str | int | str # PYI016: Duplicate union member `str` +21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` + | + = help: Remove duplicate union member `int` + +ℹ Fix +16 16 | +17 17 | # Should emit in longer unions, even if not directly adjacent. +18 18 | field3: str | str | int # PYI016: Duplicate union member `str` +19 |-field4: int | int | str # PYI016: Duplicate union member `int` + 19 |+field4: int | str # PYI016: Duplicate union member `int` +20 20 | field5: str | int | str # PYI016: Duplicate union member `str` +21 21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` +22 22 | + +PYI016.py:20:21: PYI016 [*] Duplicate union member `str` + | +18 | field3: str | str | int # PYI016: Duplicate union member `str` +19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 | field5: str | int | str # PYI016: Duplicate union member `str` + | ^^^ PYI016 +21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` + | + = help: Remove duplicate union member `str` + +ℹ Fix +17 17 | # Should emit in longer unions, even if not directly adjacent. +18 18 | field3: str | str | int # PYI016: Duplicate union member `str` +19 19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 |-field5: str | int | str # PYI016: Duplicate union member `str` + 20 |+field5: str | int # PYI016: Duplicate union member `str` +21 21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` +22 22 | +23 23 | # Shouldn't emit for non-type unions. + +PYI016.py:21:28: PYI016 [*] Duplicate union member `int` + | +19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 | field5: str | int | str # PYI016: Duplicate union member `str` +21 | field6: int | bool | str | int # PYI016: Duplicate union member `int` + | ^^^ PYI016 +22 | +23 | # Shouldn't emit for non-type unions. + | + = help: Remove duplicate union member `int` + +ℹ Fix +18 18 | field3: str | str | int # PYI016: Duplicate union member `str` +19 19 | field4: int | int | str # PYI016: Duplicate union member `int` +20 20 | field5: str | int | str # PYI016: Duplicate union member `str` +21 |-field6: int | bool | str | int # PYI016: Duplicate union member `int` + 21 |+field6: int | bool | str # PYI016: Duplicate union member `int` +22 22 | +23 23 | # Shouldn't emit for non-type unions. +24 24 | field7 = str | str + +PYI016.py:27:22: PYI016 [*] Duplicate union member `int` + | +26 | # Should emit for strangely-bracketed unions. +27 | field8: int | (str | int) # PYI016: Duplicate union member `int` + | ^^^ PYI016 +28 | +29 | # Should handle user brackets when fixing. + | + = help: Remove duplicate union member `int` + +ℹ Fix +24 24 | field7 = str | str +25 25 | +26 26 | # Should emit for strangely-bracketed unions. +27 |-field8: int | (str | int) # PYI016: Duplicate union member `int` + 27 |+field8: int | (str) # PYI016: Duplicate union member `int` +28 28 | +29 29 | # Should handle user brackets when fixing. +30 30 | field9: int | (int | str) # PYI016: Duplicate union member `int` + +PYI016.py:30:16: PYI016 [*] Duplicate union member `int` + | +29 | # Should handle user brackets when fixing. +30 | field9: int | (int | str) # PYI016: Duplicate union member `int` + | ^^^ PYI016 +31 | field10: (str | int) | str # PYI016: Duplicate union member `str` + | + = help: Remove duplicate union member `int` + +ℹ Fix +27 27 | field8: int | (str | int) # PYI016: Duplicate union member `int` +28 28 | +29 29 | # Should handle user brackets when fixing. +30 |-field9: int | (int | str) # PYI016: Duplicate union member `int` + 30 |+field9: int | (str) # PYI016: Duplicate union member `int` +31 31 | field10: (str | int) | str # PYI016: Duplicate union member `str` +32 32 | +33 33 | # Should emit for nested unions. + +PYI016.py:31:24: PYI016 [*] Duplicate union member `str` + | +29 | # Should handle user brackets when fixing. +30 | field9: int | (int | str) # PYI016: Duplicate union member `int` +31 | field10: (str | int) | str # PYI016: Duplicate union member `str` + | ^^^ PYI016 +32 | +33 | # Should emit for nested unions. + | + = help: Remove duplicate union member `str` + +ℹ Fix +28 28 | +29 29 | # Should handle user brackets when fixing. +30 30 | field9: int | (int | str) # PYI016: Duplicate union member `int` +31 |-field10: (str | int) | str # PYI016: Duplicate union member `str` + 31 |+field10: str | int # PYI016: Duplicate union member `str` +32 32 | +33 33 | # Should emit for nested unions. +34 34 | field11: dict[int | int, str] + +PYI016.py:34:21: PYI016 [*] Duplicate union member `int` + | +33 | # Should emit for nested unions. +34 | field11: dict[int | int, str] + | ^^^ PYI016 +35 | +36 | # Should emit for unions with more than two cases + | + = help: Remove duplicate union member `int` + +ℹ Fix +31 31 | field10: (str | int) | str # PYI016: Duplicate union member `str` +32 32 | +33 33 | # Should emit for nested unions. +34 |-field11: dict[int | int, str] + 34 |+field11: dict[int, str] +35 35 | +36 36 | # Should emit for unions with more than two cases +37 37 | field12: int | int | int # Error + +PYI016.py:37:16: PYI016 [*] Duplicate union member `int` + | +36 | # Should emit for unions with more than two cases +37 | field12: int | int | int # Error + | ^^^ PYI016 +38 | field13: int | int | int | int # Error + | + = help: Remove duplicate union member `int` + +ℹ Fix +34 34 | field11: dict[int | int, str] +35 35 | +36 36 | # Should emit for unions with more than two cases +37 |-field12: int | int | int # Error + 37 |+field12: int | int # Error +38 38 | field13: int | int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent + +PYI016.py:37:22: PYI016 [*] Duplicate union member `int` + | +36 | # Should emit for unions with more than two cases +37 | field12: int | int | int # Error + | ^^^ PYI016 +38 | field13: int | int | int | int # Error + | + = help: Remove duplicate union member `int` + +ℹ Fix +34 34 | field11: dict[int | int, str] +35 35 | +36 36 | # Should emit for unions with more than two cases +37 |-field12: int | int | int # Error + 37 |+field12: int | int # Error +38 38 | field13: int | int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent + +PYI016.py:38:16: PYI016 [*] Duplicate union member `int` + | +36 | # Should emit for unions with more than two cases +37 | field12: int | int | int # Error +38 | field13: int | int | int | int # Error + | ^^^ PYI016 +39 | +40 | # Should emit for unions with more than two cases, even if not directly adjacent + | + = help: Remove duplicate union member `int` + +ℹ Fix +35 35 | +36 36 | # Should emit for unions with more than two cases +37 37 | field12: int | int | int # Error +38 |-field13: int | int | int | int # Error + 38 |+field13: int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 41 | field14: int | int | str | int # Error + +PYI016.py:38:22: PYI016 [*] Duplicate union member `int` + | +36 | # Should emit for unions with more than two cases +37 | field12: int | int | int # Error +38 | field13: int | int | int | int # Error + | ^^^ PYI016 +39 | +40 | # Should emit for unions with more than two cases, even if not directly adjacent + | + = help: Remove duplicate union member `int` + +ℹ Fix +35 35 | +36 36 | # Should emit for unions with more than two cases +37 37 | field12: int | int | int # Error +38 |-field13: int | int | int | int # Error + 38 |+field13: int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 41 | field14: int | int | str | int # Error + +PYI016.py:38:28: PYI016 [*] Duplicate union member `int` + | +36 | # Should emit for unions with more than two cases +37 | field12: int | int | int # Error +38 | field13: int | int | int | int # Error + | ^^^ PYI016 +39 | +40 | # Should emit for unions with more than two cases, even if not directly adjacent + | + = help: Remove duplicate union member `int` + +ℹ Fix +35 35 | +36 36 | # Should emit for unions with more than two cases +37 37 | field12: int | int | int # Error +38 |-field13: int | int | int | int # Error + 38 |+field13: int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 41 | field14: int | int | str | int # Error + +PYI016.py:41:16: PYI016 [*] Duplicate union member `int` + | +40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 | field14: int | int | str | int # Error + | ^^^ PYI016 +42 | +43 | # Should emit for duplicate literal types; also covered by PYI030 + | + = help: Remove duplicate union member `int` + +ℹ Fix +38 38 | field13: int | int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 |-field14: int | int | str | int # Error + 41 |+field14: int | str | int # Error +42 42 | +43 43 | # Should emit for duplicate literal types; also covered by PYI030 +44 44 | field15: typing.Literal[1] | typing.Literal[1] # Error + +PYI016.py:41:28: PYI016 [*] Duplicate union member `int` + | +40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 | field14: int | int | str | int # Error + | ^^^ PYI016 +42 | +43 | # Should emit for duplicate literal types; also covered by PYI030 + | + = help: Remove duplicate union member `int` + +ℹ Fix +38 38 | field13: int | int | int | int # Error +39 39 | +40 40 | # Should emit for unions with more than two cases, even if not directly adjacent +41 |-field14: int | int | str | int # Error + 41 |+field14: int | int | str # Error +42 42 | +43 43 | # Should emit for duplicate literal types; also covered by PYI030 +44 44 | field15: typing.Literal[1] | typing.Literal[1] # Error + +PYI016.py:44:30: PYI016 [*] Duplicate union member `typing.Literal[1]` + | +43 | # Should emit for duplicate literal types; also covered by PYI030 +44 | field15: typing.Literal[1] | typing.Literal[1] # Error + | ^^^^^^^^^^^^^^^^^ PYI016 +45 | +46 | # Shouldn't emit if in new parent type + | + = help: Remove duplicate union member `typing.Literal[1]` + +ℹ Fix +41 41 | field14: int | int | str | int # Error +42 42 | +43 43 | # Should emit for duplicate literal types; also covered by PYI030 +44 |-field15: typing.Literal[1] | typing.Literal[1] # Error + 44 |+field15: typing.Literal[1] # Error +45 45 | +46 46 | # Shouldn't emit if in new parent type +47 47 | field16: int | dict[int, str] # OK + +PYI016.py:57:5: PYI016 Duplicate union member `set[int]` + | +55 | int # foo +56 | ], +57 | set[ + | _____^ +58 | | int # bar +59 | | ], + | |_____^ PYI016 +60 | ] # Error, newline and comment will not be emitted in message + | + = help: Remove duplicate union member `set[int]` + +PYI016.py:63:28: PYI016 Duplicate union member `int` + | +62 | # Should emit in cases with `typing.Union` instead of `|` +63 | field19: typing.Union[int, int] # Error + | ^^^ PYI016 +64 | +65 | # Should emit in cases with nested `typing.Union` + | + = help: Remove duplicate union member `int` + +PYI016.py:66:41: PYI016 Duplicate union member `int` + | +65 | # Should emit in cases with nested `typing.Union` +66 | field20: typing.Union[int, typing.Union[int, str]] # Error + | ^^^ PYI016 +67 | +68 | # Should emit in cases with mixed `typing.Union` and `|` + | + = help: Remove duplicate union member `int` + +PYI016.py:69:28: PYI016 [*] Duplicate union member `int` + | +68 | # Should emit in cases with mixed `typing.Union` and `|` +69 | field21: typing.Union[int, int | str] # Error + | ^^^ PYI016 +70 | +71 | # Should emit only once in cases with multiple nested `typing.Union` + | + = help: Remove duplicate union member `int` + +ℹ Fix +66 66 | field20: typing.Union[int, typing.Union[int, str]] # Error +67 67 | +68 68 | # Should emit in cases with mixed `typing.Union` and `|` +69 |-field21: typing.Union[int, int | str] # Error + 69 |+field21: typing.Union[int, str] # Error +70 70 | +71 71 | # Should emit only once in cases with multiple nested `typing.Union` +72 72 | field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error + +PYI016.py:72:41: PYI016 Duplicate union member `int` + | +71 | # Should emit only once in cases with multiple nested `typing.Union` +72 | field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error + | ^^^ PYI016 +73 | +74 | # Should emit in cases with newlines + | + = help: Remove duplicate union member `int` + +PYI016.py:72:59: PYI016 Duplicate union member `int` + | +71 | # Should emit only once in cases with multiple nested `typing.Union` +72 | field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error + | ^^^ PYI016 +73 | +74 | # Should emit in cases with newlines + | + = help: Remove duplicate union member `int` + +PYI016.py:72:64: PYI016 Duplicate union member `int` + | +71 | # Should emit only once in cases with multiple nested `typing.Union` +72 | field22: typing.Union[int, typing.Union[int, typing.Union[int, int]]] # Error + | ^^^ PYI016 +73 | +74 | # Should emit in cases with newlines + | + = help: Remove duplicate union member `int` + +PYI016.py:76:12: PYI016 [*] Duplicate union member `set[int]` + | +74 | # Should emit in cases with newlines +75 | field23: set[ # foo +76 | int] | set[int] + | ^^^^^^^^ PYI016 +77 | +78 | # Should emit twice (once for each `int` in the nested union, both of which are + | + = help: Remove duplicate union member `set[int]` + +ℹ Fix +73 73 | +74 74 | # Should emit in cases with newlines +75 75 | field23: set[ # foo +76 |- int] | set[int] + 76 |+ int] +77 77 | +78 78 | # Should emit twice (once for each `int` in the nested union, both of which are +79 79 | # duplicates of the outer `int`), but not three times (which would indicate that + +PYI016.py:81:41: PYI016 Duplicate union member `int` + | +79 | # duplicates of the outer `int`), but not three times (which would indicate that +80 | # we incorrectly re-checked the nested union). +81 | field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + | ^^^ PYI016 +82 | +83 | # Should emit twice (once for each `int` in the nested union, both of which are + | + = help: Remove duplicate union member `int` + +PYI016.py:81:46: PYI016 Duplicate union member `int` + | +79 | # duplicates of the outer `int`), but not three times (which would indicate that +80 | # we incorrectly re-checked the nested union). +81 | field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + | ^^^ PYI016 +82 | +83 | # Should emit twice (once for each `int` in the nested union, both of which are + | + = help: Remove duplicate union member `int` + +PYI016.py:86:28: PYI016 [*] Duplicate union member `int` + | +84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 | # we incorrectly re-checked the nested union). +86 | field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + | ^^^ PYI016 + | + = help: Remove duplicate union member `int` + +ℹ Fix +83 83 | # Should emit twice (once for each `int` in the nested union, both of which are +84 84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 85 | # we incorrectly re-checked the nested union). +86 |-field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + 86 |+field25: typing.Union[int, int] # PYI016: Duplicate union member `int` + +PYI016.py:86:34: PYI016 [*] Duplicate union member `int` + | +84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 | # we incorrectly re-checked the nested union). +86 | field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + | ^^^ PYI016 + | + = help: Remove duplicate union member `int` + +ℹ Fix +83 83 | # Should emit twice (once for each `int` in the nested union, both of which are +84 84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 85 | # we incorrectly re-checked the nested union). +86 |-field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + 86 |+field25: typing.Union[int, int] # PYI016: Duplicate union member `int` + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.pyi.snap index ca5312e2e9fc4..d29fea9901eb2 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.pyi.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI016_PYI016.pyi.snap @@ -471,6 +471,8 @@ PYI016.pyi:76:12: PYI016 [*] Duplicate union member `set[int]` 75 | field23: set[ # foo 76 | int] | set[int] | ^^^^^^^^ PYI016 +77 | +78 | # Should emit twice (once for each `int` in the nested union, both of which are | = help: Remove duplicate union member `set[int]` @@ -480,5 +482,62 @@ PYI016.pyi:76:12: PYI016 [*] Duplicate union member `set[int]` 75 75 | field23: set[ # foo 76 |- int] | set[int] 76 |+ int] +77 77 | +78 78 | # Should emit twice (once for each `int` in the nested union, both of which are +79 79 | # duplicates of the outer `int`), but not three times (which would indicate that + +PYI016.pyi:81:41: PYI016 Duplicate union member `int` + | +79 | # duplicates of the outer `int`), but not three times (which would indicate that +80 | # we incorrectly re-checked the nested union). +81 | field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + | ^^^ PYI016 +82 | +83 | # Should emit twice (once for each `int` in the nested union, both of which are + | + = help: Remove duplicate union member `int` + +PYI016.pyi:81:46: PYI016 Duplicate union member `int` + | +79 | # duplicates of the outer `int`), but not three times (which would indicate that +80 | # we incorrectly re-checked the nested union). +81 | field24: typing.Union[int, typing.Union[int, int]] # PYI016: Duplicate union member `int` + | ^^^ PYI016 +82 | +83 | # Should emit twice (once for each `int` in the nested union, both of which are + | + = help: Remove duplicate union member `int` + +PYI016.pyi:86:28: PYI016 [*] Duplicate union member `int` + | +84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 | # we incorrectly re-checked the nested union). +86 | field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + | ^^^ PYI016 + | + = help: Remove duplicate union member `int` + +ℹ Fix +83 83 | # Should emit twice (once for each `int` in the nested union, both of which are +84 84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 85 | # we incorrectly re-checked the nested union). +86 |-field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + 86 |+field25: typing.Union[int, int] # PYI016: Duplicate union member `int` + +PYI016.pyi:86:34: PYI016 [*] Duplicate union member `int` + | +84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 | # we incorrectly re-checked the nested union). +86 | field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + | ^^^ PYI016 + | + = help: Remove duplicate union member `int` + +ℹ Fix +83 83 | # Should emit twice (once for each `int` in the nested union, both of which are +84 84 | # duplicates of the outer `int`), but not three times (which would indicate that +85 85 | # we incorrectly re-checked the nested union). +86 |-field25: typing.Union[int, int | int] # PYI016: Duplicate union member `int` + 86 |+field25: typing.Union[int, int] # PYI016: Duplicate union member `int` diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.py.snap index d1aa2e9116558..d61c7d9e11861 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.py.snap @@ -1,4 +1,22 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI018.py:4:1: PYI018 Private TypeVar `_T` is never used + | +2 | from typing import TypeVar +3 | +4 | _T = typing.TypeVar("_T") + | ^^ PYI018 +5 | _P = TypeVar("_P") + | + +PYI018.py:5:1: PYI018 Private TypeVar `_P` is never used + | +4 | _T = typing.TypeVar("_T") +5 | _P = TypeVar("_P") + | ^^ PYI018 +6 | +7 | # OK + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.py.snap new file mode 100644 index 0000000000000..7ead8194b969f --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.py.snap @@ -0,0 +1,45 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI019.py:7:62: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar` + | +6 | class BadClass: +7 | def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.py:10:54: PYI019 Methods like `bad_instance_method` should return `typing.Self` instead of a custom `TypeVar` + | +10 | def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.py:14:54: PYI019 Methods like `bad_class_method` should return `typing.Self` instead of a custom `TypeVar` + | +13 | @classmethod +14 | def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.py:18:55: PYI019 Methods like `bad_posonly_class_method` should return `typing.Self` instead of a custom `TypeVar` + | +17 | @classmethod +18 | def bad_posonly_class_method(cls: type[_S], /) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.py:39:63: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar` + | +37 | # Python > 3.12 +38 | class PEP695BadDunderNew[T]: +39 | def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019 + | ^ PYI019 + | + +PYI019.py:42:46: PYI019 Methods like `generic_instance_method` should return `typing.Self` instead of a custom `TypeVar` + | +42 | def generic_instance_method[S](self: S) -> S: ... # PYI019 + | ^ PYI019 + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.pyi.snap new file mode 100644 index 0000000000000..03c5bbb5bed24 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI019_PYI019.pyi.snap @@ -0,0 +1,45 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI019.pyi:7:62: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar` + | +6 | class BadClass: +7 | def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.pyi:10:54: PYI019 Methods like `bad_instance_method` should return `typing.Self` instead of a custom `TypeVar` + | +10 | def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.pyi:14:54: PYI019 Methods like `bad_class_method` should return `typing.Self` instead of a custom `TypeVar` + | +13 | @classmethod +14 | def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.pyi:18:55: PYI019 Methods like `bad_posonly_class_method` should return `typing.Self` instead of a custom `TypeVar` + | +17 | @classmethod +18 | def bad_posonly_class_method(cls: type[_S], /) -> _S: ... # PYI019 + | ^^ PYI019 + | + +PYI019.pyi:39:63: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar` + | +37 | # Python > 3.12 +38 | class PEP695BadDunderNew[T]: +39 | def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019 + | ^ PYI019 + | + +PYI019.pyi:42:46: PYI019 Methods like `generic_instance_method` should return `typing.Self` instead of a custom `TypeVar` + | +42 | def generic_instance_method[S](self: S) -> S: ... # PYI019 + | ^ PYI019 + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI024_PYI024.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI024_PYI024.py.snap index d1aa2e9116558..aacfa649848ca 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI024_PYI024.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI024_PYI024.py.snap @@ -1,4 +1,37 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI024.py:3:9: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple` + | +1 | import collections +2 | +3 | person: collections.namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" + | ^^^^^^^^^^^^^^^^^^^^^^ PYI024 +4 | +5 | from collections import namedtuple + | + = help: Replace with `typing.NamedTuple` + +PYI024.py:7:9: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple` + | +5 | from collections import namedtuple +6 | +7 | person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" + | ^^^^^^^^^^ PYI024 +8 | +9 | person = namedtuple( + | + = help: Replace with `typing.NamedTuple` + +PYI024.py:9:10: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple` + | + 7 | person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" + 8 | + 9 | person = namedtuple( + | ^^^^^^^^^^ PYI024 +10 | "Person", ["name", "age"] +11 | ) # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple" + | + = help: Replace with `typing.NamedTuple` + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI025_PYI025.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI025_PYI025.py.snap index d1aa2e9116558..606cc41cafe43 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI025_PYI025.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI025_PYI025.py.snap @@ -1,4 +1,46 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI025.py:10:33: PYI025 [*] Use `from collections.abc import Set as AbstractSet` to avoid confusion with the `set` builtin + | + 9 | def f(): +10 | from collections.abc import Set # PYI025 + | ^^^ PYI025 + | + = help: Alias `Set` to `AbstractSet` + +ℹ Suggested fix +7 7 | +8 8 | +9 9 | def f(): +10 |- from collections.abc import Set # PYI025 + 10 |+ from collections.abc import Set as AbstractSet # PYI025 +11 11 | +12 12 | +13 13 | def f(): + +PYI025.py:14:51: PYI025 [*] Use `from collections.abc import Set as AbstractSet` to avoid confusion with the `set` builtin + | +13 | def f(): +14 | from collections.abc import Container, Sized, Set, ValuesView # PYI025 + | ^^^ PYI025 +15 | +16 | GLOBAL: Set[int] = set() + | + = help: Alias `Set` to `AbstractSet` + +ℹ Suggested fix +11 11 | +12 12 | +13 13 | def f(): +14 |- from collections.abc import Container, Sized, Set, ValuesView # PYI025 + 14 |+ from collections.abc import Container, Sized, Set as AbstractSet, ValuesView # PYI025 +15 15 | +16 |- GLOBAL: Set[int] = set() + 16 |+ GLOBAL: AbstractSet[int] = set() +17 17 | +18 18 | class Class: +19 |- member: Set[int] + 19 |+ member: AbstractSet[int] + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI026_PYI026.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI026_PYI026.pyi.snap index 075d94d02c900..b0399539580e3 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI026_PYI026.pyi.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI026_PYI026.pyi.snap @@ -1,7 +1,7 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- -PYI026.pyi:3:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `NewAny: typing.TypeAlias = Any` +PYI026.pyi:3:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `NewAny: TypeAlias = Any` | 1 | from typing import Literal, Any 2 | @@ -10,7 +10,7 @@ PYI026.pyi:3:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `NewAny: 4 | OptionalStr = typing.Optional[str] 5 | Foo = Literal["foo"] | - = help: Add `typing.TypeAlias` annotation + = help: Add `TypeAlias` annotation ℹ Suggested fix 1 |-from typing import Literal, Any @@ -22,7 +22,7 @@ PYI026.pyi:3:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `NewAny: 5 5 | Foo = Literal["foo"] 6 6 | IntOrStr = int | str -PYI026.pyi:4:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `OptionalStr: typing.TypeAlias = typing.Optional[str]` +PYI026.pyi:4:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `OptionalStr: TypeAlias = typing.Optional[str]` | 3 | NewAny = Any 4 | OptionalStr = typing.Optional[str] @@ -30,7 +30,7 @@ PYI026.pyi:4:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Optiona 5 | Foo = Literal["foo"] 6 | IntOrStr = int | str | - = help: Add `typing.TypeAlias` annotation + = help: Add `TypeAlias` annotation ℹ Suggested fix 1 |-from typing import Literal, Any @@ -43,7 +43,7 @@ PYI026.pyi:4:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Optiona 6 6 | IntOrStr = int | str 7 7 | AliasNone = None -PYI026.pyi:5:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Foo: typing.TypeAlias = Literal["foo"]` +PYI026.pyi:5:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Foo: TypeAlias = Literal["foo"]` | 3 | NewAny = Any 4 | OptionalStr = typing.Optional[str] @@ -52,7 +52,7 @@ PYI026.pyi:5:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Foo: ty 6 | IntOrStr = int | str 7 | AliasNone = None | - = help: Add `typing.TypeAlias` annotation + = help: Add `TypeAlias` annotation ℹ Suggested fix 1 |-from typing import Literal, Any @@ -66,7 +66,7 @@ PYI026.pyi:5:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `Foo: ty 7 7 | AliasNone = None 8 8 | -PYI026.pyi:6:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `IntOrStr: typing.TypeAlias = int | str` +PYI026.pyi:6:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `IntOrStr: TypeAlias = int | str` | 4 | OptionalStr = typing.Optional[str] 5 | Foo = Literal["foo"] @@ -74,7 +74,7 @@ PYI026.pyi:6:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `IntOrSt | ^^^^^^^^ PYI026 7 | AliasNone = None | - = help: Add `typing.TypeAlias` annotation + = help: Add `TypeAlias` annotation ℹ Suggested fix 1 |-from typing import Literal, Any @@ -89,7 +89,7 @@ PYI026.pyi:6:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `IntOrSt 8 8 | 9 9 | NewAny: typing.TypeAlias = Any -PYI026.pyi:7:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `AliasNone: typing.TypeAlias = None` +PYI026.pyi:7:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `AliasNone: TypeAlias = None` | 5 | Foo = Literal["foo"] 6 | IntOrStr = int | str @@ -98,7 +98,7 @@ PYI026.pyi:7:1: PYI026 [*] Use `typing.TypeAlias` for type alias, e.g., `AliasNo 8 | 9 | NewAny: typing.TypeAlias = Any | - = help: Add `typing.TypeAlias` annotation + = help: Add `TypeAlias` annotation ℹ Suggested fix 1 |-from typing import Literal, Any diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI030_PYI030.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI030_PYI030.py.snap index d1aa2e9116558..204ae03602c62 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI030_PYI030.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI030_PYI030.py.snap @@ -1,4 +1,110 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | + 8 | # Should emit for duplicate field types. + 9 | field2: Literal[1] | Literal[2] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +10 | +11 | # Should emit for union types in arguments. + | + +PYI030.py:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +11 | # Should emit for union types in arguments. +12 | def func1(arg1: Literal[1] | Literal[2]): # Error + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +13 | print(arg1) + | + +PYI030.py:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +16 | # Should emit for unions in return types. +17 | def func2() -> Literal[1] | Literal[2]: # Error + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +18 | return "my Literal[1]ing" + | + +PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +21 | # Should emit in longer unions, even if not directly adjacent. +22 | field3: Literal[1] | Literal[2] | str # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +23 | field4: str | Literal[1] | Literal[2] # Error +24 | field5: Literal[1] | str | Literal[2] # Error + | + +PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +21 | # Should emit in longer unions, even if not directly adjacent. +22 | field3: Literal[1] | Literal[2] | str # Error +23 | field4: str | Literal[1] | Literal[2] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +24 | field5: Literal[1] | str | Literal[2] # Error +25 | field6: Literal[1] | bool | Literal[2] | str # Error + | + +PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +22 | field3: Literal[1] | Literal[2] | str # Error +23 | field4: str | Literal[1] | Literal[2] # Error +24 | field5: Literal[1] | str | Literal[2] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +25 | field6: Literal[1] | bool | Literal[2] | str # Error + | + +PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +23 | field4: str | Literal[1] | Literal[2] # Error +24 | field5: Literal[1] | str | Literal[2] # Error +25 | field6: Literal[1] | bool | Literal[2] | str # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +26 | +27 | # Should emit for non-type unions. + | + +PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +27 | # Should emit for non-type unions. +28 | field7 = Literal[1] | Literal[2] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +29 | +30 | # Should emit for parenthesized unions. + | + +PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +30 | # Should emit for parenthesized unions. +31 | field8: Literal[1] | (Literal[2] | str) # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +32 | +33 | # Should handle user parentheses when fixing. + | + +PYI030.py:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +33 | # Should handle user parentheses when fixing. +34 | field9: Literal[1] | (Literal[2] | str) # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +35 | field10: (Literal[1] | str) | Literal[2] # Error + | + +PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +33 | # Should handle user parentheses when fixing. +34 | field9: Literal[1] | (Literal[2] | str) # Error +35 | field10: (Literal[1] | str) | Literal[2] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 +36 | +37 | # Should emit for union in generic parent type. + | + +PYI030.py:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` + | +37 | # Should emit for union in generic parent type. +38 | field11: dict[Literal[1] | Literal[2], str] # Error + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI032_PYI032.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI032_PYI032.py.snap index d1aa2e9116558..ddf2b4d458f49 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI032_PYI032.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI032_PYI032.py.snap @@ -1,4 +1,42 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI032.py:6:29: PYI032 [*] Prefer `object` to `Any` for the second parameter to `__eq__` + | +5 | class Bad: +6 | def __eq__(self, other: Any) -> bool: ... # Y032 + | ^^^ PYI032 +7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032 + | + = help: Replace with `object` + +ℹ Fix +3 3 | +4 4 | +5 5 | class Bad: +6 |- def __eq__(self, other: Any) -> bool: ... # Y032 + 6 |+ def __eq__(self, other: object) -> bool: ... # Y032 +7 7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032 +8 8 | +9 9 | + +PYI032.py:7:29: PYI032 [*] Prefer `object` to `Any` for the second parameter to `__ne__` + | +5 | class Bad: +6 | def __eq__(self, other: Any) -> bool: ... # Y032 +7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032 + | ^^^^^^^^^^ PYI032 + | + = help: Replace with `object` + +ℹ Fix +4 4 | +5 5 | class Bad: +6 6 | def __eq__(self, other: Any) -> bool: ... # Y032 +7 |- def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032 + 7 |+ def __ne__(self, other: object) -> typing.Any: ... # Y032 +8 8 | +9 9 | +10 10 | class Good: + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI034_PYI034.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI034_PYI034.py.snap index d1aa2e9116558..a1f33f746f1fb 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI034_PYI034.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI034_PYI034.py.snap @@ -1,4 +1,92 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI034.py:19:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime + | +17 | object +18 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3 +19 | def __new__(cls, *args: Any, **kwargs: Any) -> Bad: + | ^^^^^^^ PYI034 +20 | ... # Y034 "__new__" methods usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__new__", e.g. "def __new__(cls, *args: Any, **kwargs: Any) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:34:9: PYI034 `__enter__` methods in classes like `Bad` usually return `self` at runtime + | +32 | ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods +33 | +34 | def __enter__(self) -> Bad: + | ^^^^^^^^^ PYI034 +35 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:37:15: PYI034 `__aenter__` methods in classes like `Bad` usually return `self` at runtime + | +35 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." +36 | +37 | async def __aenter__(self) -> Bad: + | ^^^^^^^^^^ PYI034 +38 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:40:9: PYI034 `__iadd__` methods in classes like `Bad` usually return `self` at runtime + | +38 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." +39 | +40 | def __iadd__(self, other: Bad) -> Bad: + | ^^^^^^^^ PYI034 +41 | ... # Y034 "__iadd__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__iadd__", e.g. "def __iadd__(self, other: Bad) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:163:9: PYI034 `__iter__` methods in classes like `BadIterator1` usually return `self` at runtime + | +162 | class BadIterator1(Iterator[int]): +163 | def __iter__(self) -> Iterator[int]: + | ^^^^^^^^ PYI034 +164 | ... # Y034 "__iter__" methods in classes like "BadIterator1" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator1.__iter__", e.g. "def __iter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:170:9: PYI034 `__iter__` methods in classes like `BadIterator2` usually return `self` at runtime + | +168 | typing.Iterator[int] +169 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) +170 | def __iter__(self) -> Iterator[int]: + | ^^^^^^^^ PYI034 +171 | ... # Y034 "__iter__" methods in classes like "BadIterator2" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator2.__iter__", e.g. "def __iter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:177:9: PYI034 `__iter__` methods in classes like `BadIterator3` usually return `self` at runtime + | +175 | typing.Iterator[int] +176 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) +177 | def __iter__(self) -> collections.abc.Iterator[int]: + | ^^^^^^^^ PYI034 +178 | ... # Y034 "__iter__" methods in classes like "BadIterator3" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator3.__iter__", e.g. "def __iter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:183:9: PYI034 `__iter__` methods in classes like `BadIterator4` usually return `self` at runtime + | +181 | class BadIterator4(Iterator[int]): +182 | # Note: *Iterable*, not *Iterator*, returned! +183 | def __iter__(self) -> Iterable[int]: + | ^^^^^^^^ PYI034 +184 | ... # Y034 "__iter__" methods in classes like "BadIterator4" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator4.__iter__", e.g. "def __iter__(self) -> Self: ..." + | + = help: Consider using `typing_extensions.Self` as return type + +PYI034.py:193:9: PYI034 `__aiter__` methods in classes like `BadAsyncIterator` usually return `self` at runtime + | +192 | class BadAsyncIterator(collections.abc.AsyncIterator[str]): +193 | def __aiter__(self) -> typing.AsyncIterator[str]: + | ^^^^^^^^^ PYI034 +194 | ... # Y034 "__aiter__" methods in classes like "BadAsyncIterator" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadAsyncIterator.__aiter__", e.g. "def __aiter__(self) -> Self: ..." # Y022 Use "collections.abc.AsyncIterator[T]" instead of "typing.AsyncIterator[T]" (PEP 585 syntax) + | + = help: Consider using `typing_extensions.Self` as return type + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI036_PYI036.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI036_PYI036.py.snap index d1aa2e9116558..e4a422090f829 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI036_PYI036.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI036_PYI036.py.snap @@ -1,4 +1,161 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI036.py:54:31: PYI036 [*] Star-args in `__exit__` should be annotated with `object` + | +53 | class BadOne: +54 | def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation + | ^^^ PYI036 +55 | async def __aexit__(self) -> None: ... # PYI036: Missing args + | + = help: Annotate star-args with `object` + +ℹ Fix +51 51 | +52 52 | +53 53 | class BadOne: +54 |- def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation + 54 |+ def __exit__(self, *args: object) -> None: ... # PYI036: Bad star-args annotation +55 55 | async def __aexit__(self) -> None: ... # PYI036: Missing args +56 56 | +57 57 | class BadTwo: + +PYI036.py:55:24: PYI036 If there are no star-args, `__aexit__` should have at least 3 non-keyword-only args (excluding `self`) + | +53 | class BadOne: +54 | def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation +55 | async def __aexit__(self) -> None: ... # PYI036: Missing args + | ^^^^^^ PYI036 +56 | +57 | class BadTwo: + | + +PYI036.py:58:38: PYI036 All arguments after the first four in `__exit__` must have a default value + | +57 | class BadTwo: +58 | def __exit__(self, typ, exc, tb, weird_extra_arg) -> None: ... # PYI036: Extra arg must have default + | ^^^^^^^^^^^^^^^ PYI036 +59 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ...# PYI036: Extra arg must have default + | + +PYI036.py:59:48: PYI036 All keyword-only arguments in `__aexit__` must have a default value + | +57 | class BadTwo: +58 | def __exit__(self, typ, exc, tb, weird_extra_arg) -> None: ... # PYI036: Extra arg must have default +59 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ...# PYI036: Extra arg must have default + | ^^^^^^^^^^^^^^^ PYI036 +60 | +61 | class BadThree: + | + +PYI036.py:62:29: PYI036 The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None` + | +61 | class BadThree: +62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation + | ^^^^^^^^^^^^^^^^^^^ PYI036 +63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation + | + +PYI036.py:63:73: PYI036 The second argument in `__aexit__` should be annotated with `object` or `BaseException | None` + | +61 | class BadThree: +62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation +63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation + | ^^^^^^^^^^^^^ PYI036 +64 | +65 | class BadFour: + | + +PYI036.py:63:94: PYI036 The third argument in `__aexit__` should be annotated with `object` or `types.TracebackType | None` + | +61 | class BadThree: +62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation +63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation + | ^^^^^^^^^^^^^ PYI036 +64 | +65 | class BadFour: + | + +PYI036.py:66:111: PYI036 The third argument in `__exit__` should be annotated with `object` or `types.TracebackType | None` + | +65 | class BadFour: +66 | def __exit__(self, typ: typing.Optional[type[BaseException]], exc: typing.Union[BaseException, None], tb: TracebackType) -> None: ... # PYI036: Third arg has bad annotation + | ^^^^^^^^^^^^^ PYI036 +67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation + | + +PYI036.py:67:101: PYI036 The third argument in `__aexit__` should be annotated with `object` or `types.TracebackType | None` + | +65 | class BadFour: +66 | def __exit__(self, typ: typing.Optional[type[BaseException]], exc: typing.Union[BaseException, None], tb: TracebackType) -> None: ... # PYI036: Third arg has bad annotation +67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI036 +68 | +69 | class BadFive: + | + +PYI036.py:70:29: PYI036 The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None` + | +69 | class BadFive: +70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation + | ^^^^^^^^^^^^^^^^^^^^ PYI036 +71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation + | + +PYI036.py:70:58: PYI036 [*] Star-args in `__exit__` should be annotated with `object` + | +69 | class BadFive: +70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation + | ^^^^^^^^^ PYI036 +71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation + | + = help: Annotate star-args with `object` + +ℹ Fix +67 67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation +68 68 | +69 69 | class BadFive: +70 |- def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation + 70 |+ def __exit__(self, typ: BaseException | None, *args: object) -> bool: ... # PYI036: Bad star-args annotation +71 71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation +72 72 | +73 73 | class BadSix: + +PYI036.py:71:74: PYI036 [*] Star-args in `__aexit__` should be annotated with `object` + | +69 | class BadFive: +70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation +71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation + | ^^^ PYI036 +72 | +73 | class BadSix: + | + = help: Annotate star-args with `object` + +ℹ Fix +68 68 | +69 69 | class BadFive: +70 70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation +71 |- async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation + 71 |+ async def __aexit__(self, /, typ: type[BaseException] | None, *args: object) -> Awaitable[None]: ... # PYI036: Bad star-args annotation +72 72 | +73 73 | class BadSix: +74 74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default + +PYI036.py:74:38: PYI036 All arguments after the first four in `__exit__` must have a default value + | +73 | class BadSix: +74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default + | ^^^^^^^^^^^^^^^ PYI036 +75 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ... # PYI036: kwargs must have default + | + +PYI036.py:75:48: PYI036 All keyword-only arguments in `__aexit__` must have a default value + | +73 | class BadSix: +74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default +75 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ... # PYI036: kwargs must have default + | ^^^^^^^^^^^^^^^ PYI036 + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI041_PYI041.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI041_PYI041.py.snap index d1aa2e9116558..de8a65f4b9739 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI041_PYI041.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI041_PYI041.py.snap @@ -1,4 +1,50 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI041.py:22:14: PYI041 Use `float` instead of `int | float` + | +22 | def f0(arg1: float | int) -> None: + | ^^^^^^^^^^^ PYI041 +23 | ... + | + +PYI041.py:26:30: PYI041 Use `complex` instead of `float | complex` + | +26 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041 +27 | ... + | + +PYI041.py:30:28: PYI041 Use `float` instead of `int | float` + | +30 | def f2(arg1: int, /, arg2: int | int | float) -> None: + | ^^^^^^^^^^^^^^^^^ PYI041 +31 | ... + | + +PYI041.py:38:24: PYI041 Use `float` instead of `int | float` + | +38 | async def f4(**kwargs: int | int | float) -> None: + | ^^^^^^^^^^^^^^^^^ PYI041 +39 | ... + | + +PYI041.py:46:24: PYI041 Use `complex` instead of `float | complex` + | +44 | ... +45 | +46 | def bad(self, arg: int | float | complex) -> None: + | ^^^^^^^^^^^^^^^^^^^^^ PYI041 +47 | ... + | + +PYI041.py:46:24: PYI041 Use `complex` instead of `int | complex` + | +44 | ... +45 | +46 | def bad(self, arg: int | float | complex) -> None: + | ^^^^^^^^^^^^^^^^^^^^^ PYI041 +47 | ... + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI042_PYI042.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI042_PYI042.py.snap index d1aa2e9116558..e71725b7754c3 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI042_PYI042.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI042_PYI042.py.snap @@ -1,4 +1,32 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI042.py:10:1: PYI042 Type alias `just_literals_pipe_union` should be CamelCase + | + 8 | ) + 9 | +10 | just_literals_pipe_union: TypeAlias = ( + | ^^^^^^^^^^^^^^^^^^^^^^^^ PYI042 +11 | Literal[True] | Literal["idk"] +12 | ) # PYI042, since not camel case + | + +PYI042.py:19:1: PYI042 Type alias `snake_case_alias1` should be CamelCase + | +17 | _PrivateAliasS2: TypeAlias = Annotated[str, "also okay"] +18 | +19 | snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case + | ^^^^^^^^^^^^^^^^^ PYI042 +20 | _snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case +21 | Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case + | + +PYI042.py:20:1: PYI042 Type alias `_snake_case_alias2` should be CamelCase + | +19 | snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case +20 | _snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case + | ^^^^^^^^^^^^^^^^^^ PYI042 +21 | Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI043_PYI043.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI043_PYI043.py.snap index d1aa2e9116558..84453cd4e7f5f 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI043_PYI043.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI043_PYI043.py.snap @@ -1,4 +1,33 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI043.py:10:1: PYI043 Private type alias `_PrivateAliasT` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`) + | + 8 | ) + 9 | +10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T + | ^^^^^^^^^^^^^^ PYI043 +11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T +12 | _PrivateAliasT3: TypeAlias = Literal[ + | + +PYI043.py:11:1: PYI043 Private type alias `_PrivateAliasT2` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`) + | +10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T +11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T + | ^^^^^^^^^^^^^^^ PYI043 +12 | _PrivateAliasT3: TypeAlias = Literal[ +13 | "not", "a", "chance" + | + +PYI043.py:12:1: PYI043 Private type alias `_PrivateAliasT3` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`) + | +10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T +11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T +12 | _PrivateAliasT3: TypeAlias = Literal[ + | ^^^^^^^^^^^^^^^ PYI043 +13 | "not", "a", "chance" +14 | ] # PYI043, since this ends in a T + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI045_PYI045.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI045_PYI045.py.snap index d1aa2e9116558..cb8af8e42ab5c 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI045_PYI045.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI045_PYI045.py.snap @@ -1,4 +1,60 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI045.py:12:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable` + | +11 | class TypingIterableTReturn: +12 | def __iter__(self) -> typing.Iterable[int]: + | ^^^^^^^^^^^^^^^^^^^^ PYI045 +13 | ... + | + +PYI045.py:20:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable` + | +19 | class TypingIterableReturn: +20 | def __iter__(self) -> typing.Iterable: + | ^^^^^^^^^^^^^^^ PYI045 +21 | ... + | + +PYI045.py:28:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable` + | +27 | class CollectionsIterableTReturn: +28 | def __iter__(self) -> collections.abc.Iterable[int]: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI045 +29 | ... + | + +PYI045.py:36:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable` + | +35 | class CollectionsIterableReturn: +36 | def __iter__(self) -> collections.abc.Iterable: + | ^^^^^^^^^^^^^^^^^^^^^^^^ PYI045 +37 | ... + | + +PYI045.py:44:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable` + | +43 | class IterableReturn: +44 | def __iter__(self) -> Iterable: + | ^^^^^^^^ PYI045 +45 | ... + | + +PYI045.py:79:28: PYI045 `__aiter__` methods should return an `AsyncIterator`, not an `AsyncIterable` + | +78 | class TypingAsyncIterableTReturn: +79 | def __aiter__(self) -> typing.AsyncIterable[int]: + | ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI045 +80 | ... + | + +PYI045.py:84:28: PYI045 `__aiter__` methods should return an `AsyncIterator`, not an `AsyncIterable` + | +83 | class TypingAsyncIterableReturn: +84 | def __aiter__(self) -> typing.AsyncIterable: + | ^^^^^^^^^^^^^^^^^^^^ PYI045 +85 | ... + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI046_PYI046.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI046_PYI046.py.snap index d1aa2e9116558..463704b900ec9 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI046_PYI046.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI046_PYI046.py.snap @@ -1,4 +1,18 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI046.py:5:7: PYI046 Private protocol `_Foo` is never used + | +5 | class _Foo(Protocol): + | ^^^^ PYI046 +6 | bar: int + | + +PYI046.py:9:7: PYI046 Private protocol `_Bar` is never used + | + 9 | class _Bar(typing.Protocol): + | ^^^^ PYI046 +10 | bar: int + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI047_PYI047.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI047_PYI047.py.snap index d1aa2e9116558..ced54687f1a66 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI047_PYI047.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI047_PYI047.py.snap @@ -1,4 +1,20 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI047.py:6:1: PYI047 Private TypeAlias `_UnusedPrivateTypeAlias` is never used + | +6 | _UnusedPrivateTypeAlias: TypeAlias = int | None + | ^^^^^^^^^^^^^^^^^^^^^^^ PYI047 +7 | _T: typing.TypeAlias = str + | + +PYI047.py:7:1: PYI047 Private TypeAlias `_T` is never used + | +6 | _UnusedPrivateTypeAlias: TypeAlias = int | None +7 | _T: typing.TypeAlias = str + | ^^ PYI047 +8 | +9 | # OK + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI049_PYI049.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI049_PYI049.py.snap index d1aa2e9116558..46c42efa8cd57 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI049_PYI049.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI049_PYI049.py.snap @@ -1,4 +1,18 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI049.py:5:7: PYI049 Private TypedDict `_UnusedTypedDict` is never used + | +5 | class _UnusedTypedDict(TypedDict): + | ^^^^^^^^^^^^^^^^ PYI049 +6 | foo: str + | + +PYI049.py:9:7: PYI049 Private TypedDict `_UnusedTypedDict2` is never used + | + 9 | class _UnusedTypedDict2(typing.TypedDict): + | ^^^^^^^^^^^^^^^^^ PYI049 +10 | bar: int + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.py.snap index d1aa2e9116558..492243cf19e22 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.py.snap @@ -1,4 +1,25 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI050.py:13:24: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations + | +13 | def foo_no_return(arg: NoReturn): + | ^^^^^^^^ PYI050 +14 | ... + | + +PYI050.py:23:44: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations + | +23 | def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): + | ^^^^^^^^ PYI050 +24 | ... + | + +PYI050.py:27:47: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations + | +27 | def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): + | ^^^^^^^^ PYI050 +28 | ... + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap index f476783f00d10..2eafac78058b5 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap @@ -1,7 +1,7 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- -PYI050.pyi:6:24: PYI050 Prefer `typing_extensions.Never` over `NoReturn` for argument annotations +PYI050.pyi:6:24: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations | 4 | def foo(arg): ... 5 | def foo_int(arg: int): ... @@ -11,7 +11,7 @@ PYI050.pyi:6:24: PYI050 Prefer `typing_extensions.Never` over `NoReturn` for arg 8 | arg: typing_extensions.NoReturn, | -PYI050.pyi:10:44: PYI050 Prefer `typing_extensions.Never` over `NoReturn` for argument annotations +PYI050.pyi:10:44: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations | 8 | arg: typing_extensions.NoReturn, 9 | ): ... # Error: PYI050 @@ -21,7 +21,7 @@ PYI050.pyi:10:44: PYI050 Prefer `typing_extensions.Never` over `NoReturn` for ar 12 | def foo_never(arg: Never): ... | -PYI050.pyi:11:47: PYI050 Prefer `typing_extensions.Never` over `NoReturn` for argument annotations +PYI050.pyi:11:47: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations | 9 | ): ... # Error: PYI050 10 | def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): ... # Error: PYI050 diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.py.snap new file mode 100644 index 0000000000000..3c6c91602c00f --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.py.snap @@ -0,0 +1,90 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI051.py:4:18: PYI051 `Literal["foo"]` is redundant in a union with `str` + | +2 | from typing import Literal, TypeAlias, Union +3 | +4 | A: str | Literal["foo"] + | ^^^^^ PYI051 +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | + +PYI051.py:5:37: PYI051 `Literal[b"bar"]` is redundant in a union with `bytes` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] + | ^^^^^^ PYI051 +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.py:5:45: PYI051 `Literal[b"foo"]` is redundant in a union with `bytes` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] + | ^^^^^^ PYI051 +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.py:6:37: PYI051 `Literal[5]` is redundant in a union with `int` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | ^ PYI051 +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.py:6:67: PYI051 `Literal["foo"]` is redundant in a union with `str` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | ^^^^^ PYI051 +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.py:7:37: PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes` + | +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | ^^^^^^^^^^^^ PYI051 +8 | +9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | + +PYI051.py:7:51: PYI051 `Literal[42]` is redundant in a union with `int` + | +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | ^^ PYI051 +8 | +9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | + +PYI051.py:9:31: PYI051 `Literal[1J]` is redundant in a union with `complex` + | + 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + 8 | + 9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | ^^ PYI051 +10 | +11 | # OK + | + +PYI051.py:9:53: PYI051 `Literal[3.14]` is redundant in a union with `float` + | + 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + 8 | + 9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | ^^^^ PYI051 +10 | +11 | # OK + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.pyi.snap new file mode 100644 index 0000000000000..14b0115513cba --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI051_PYI051.pyi.snap @@ -0,0 +1,90 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI051.pyi:4:18: PYI051 `Literal["foo"]` is redundant in a union with `str` + | +2 | from typing import Literal, TypeAlias, Union +3 | +4 | A: str | Literal["foo"] + | ^^^^^ PYI051 +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | + +PYI051.pyi:5:37: PYI051 `Literal[b"bar"]` is redundant in a union with `bytes` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] + | ^^^^^^ PYI051 +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.pyi:5:45: PYI051 `Literal[b"foo"]` is redundant in a union with `bytes` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] + | ^^^^^^ PYI051 +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.pyi:6:37: PYI051 `Literal[5]` is redundant in a union with `int` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | ^ PYI051 +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.pyi:6:67: PYI051 `Literal["foo"]` is redundant in a union with `str` + | +4 | A: str | Literal["foo"] +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] + | ^^^^^ PYI051 +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | + +PYI051.pyi:7:37: PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes` + | +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | ^^^^^^^^^^^^ PYI051 +8 | +9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | + +PYI051.pyi:7:51: PYI051 `Literal[42]` is redundant in a union with `int` + | +5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] +6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] +7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + | ^^ PYI051 +8 | +9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | + +PYI051.pyi:9:31: PYI051 `Literal[1J]` is redundant in a union with `complex` + | + 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + 8 | + 9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | ^^ PYI051 +10 | +11 | # OK + | + +PYI051.pyi:9:53: PYI051 `Literal[3.14]` is redundant in a union with `float` + | + 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] + 8 | + 9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... + | ^^^^ PYI051 +10 | +11 | # OK + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.py.snap new file mode 100644 index 0000000000000..8f474e08d7d13 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.py.snap @@ -0,0 +1,12 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI055.py:31:11: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`. + | +29 | def func(): +30 | # PYI055 +31 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.pyi.snap new file mode 100644 index 0000000000000..a8262366eddb1 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI055_PYI055.pyi.snap @@ -0,0 +1,79 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI055.pyi:4:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`. + | +2 | from typing import Union +3 | +4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +5 | x: type[int] | type[str] | type[float] +6 | y: builtins.type[int] | type[str] | builtins.type[complex] + | + +PYI055.pyi:5:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | float]`. + | +4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex] +5 | x: type[int] | type[str] | type[float] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +6 | y: builtins.type[int] | type[str] | builtins.type[complex] +7 | z: Union[type[float], type[complex]] + | + +PYI055.pyi:6:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`. + | +4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex] +5 | x: type[int] | type[str] | type[float] +6 | y: builtins.type[int] | type[str] | builtins.type[complex] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +7 | z: Union[type[float], type[complex]] +8 | z: Union[type[float, int], type[complex]] + | + +PYI055.pyi:7:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`. + | +5 | x: type[int] | type[str] | type[float] +6 | y: builtins.type[int] | type[str] | builtins.type[complex] +7 | z: Union[type[float], type[complex]] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +8 | z: Union[type[float, int], type[complex]] + | + +PYI055.pyi:8:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`. + | + 6 | y: builtins.type[int] | type[str] | builtins.type[complex] + 7 | z: Union[type[float], type[complex]] + 8 | z: Union[type[float, int], type[complex]] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 + 9 | +10 | def func(arg: type[int] | str | type[float]) -> None: ... + | + +PYI055.pyi:10:15: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`. + | + 8 | z: Union[type[float, int], type[complex]] + 9 | +10 | def func(arg: type[int] | str | type[float]) -> None: ... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +11 | +12 | # OK + | + +PYI055.pyi:20:7: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`. + | +19 | # OK +20 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 +21 | +22 | def func(): + | + +PYI055.pyi:24:11: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`. + | +22 | def func(): +23 | # PYI055 +24 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055 + | + + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI056_PYI056.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI056_PYI056.py.snap index d1aa2e9116558..4c239c9c0725f 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI056_PYI056.py.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI056_PYI056.py.snap @@ -1,4 +1,32 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- +PYI056.py:4:1: PYI056 Calling `.append()` on `__all__` may not be supported by all type checkers (use `+=` instead) + | +3 | # Errors +4 | __all__.append("D") + | ^^^^^^^^^^^^^^ PYI056 +5 | __all__.extend(["E", "Foo"]) +6 | __all__.remove("A") + | + +PYI056.py:5:1: PYI056 Calling `.extend()` on `__all__` may not be supported by all type checkers (use `+=` instead) + | +3 | # Errors +4 | __all__.append("D") +5 | __all__.extend(["E", "Foo"]) + | ^^^^^^^^^^^^^^ PYI056 +6 | __all__.remove("A") + | + +PYI056.py:6:1: PYI056 Calling `.remove()` on `__all__` may not be supported by all type checkers (use `+=` instead) + | +4 | __all__.append("D") +5 | __all__.extend(["E", "Foo"]) +6 | __all__.remove("A") + | ^^^^^^^^^^^^^^ PYI056 +7 | +8 | # OK + | + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.py.snap new file mode 100644 index 0000000000000..d1aa2e9116558 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.pyi.snap new file mode 100644 index 0000000000000..a78ca465b9180 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__py38_PYI026_PYI026.pyi.snap @@ -0,0 +1,117 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI026.pyi:3:1: PYI026 [*] Use `typing_extensions.TypeAlias` for type alias, e.g., `NewAny: TypeAlias = Any` + | +1 | from typing import Literal, Any +2 | +3 | NewAny = Any + | ^^^^^^ PYI026 +4 | OptionalStr = typing.Optional[str] +5 | Foo = Literal["foo"] + | + = help: Add `TypeAlias` annotation + +ℹ Suggested fix +1 1 | from typing import Literal, Any + 2 |+import typing_extensions +2 3 | +3 |-NewAny = Any + 4 |+NewAny: typing_extensions.TypeAlias = Any +4 5 | OptionalStr = typing.Optional[str] +5 6 | Foo = Literal["foo"] +6 7 | IntOrStr = int | str + +PYI026.pyi:4:1: PYI026 [*] Use `typing_extensions.TypeAlias` for type alias, e.g., `OptionalStr: TypeAlias = typing.Optional[str]` + | +3 | NewAny = Any +4 | OptionalStr = typing.Optional[str] + | ^^^^^^^^^^^ PYI026 +5 | Foo = Literal["foo"] +6 | IntOrStr = int | str + | + = help: Add `TypeAlias` annotation + +ℹ Suggested fix +1 1 | from typing import Literal, Any + 2 |+import typing_extensions +2 3 | +3 4 | NewAny = Any +4 |-OptionalStr = typing.Optional[str] + 5 |+OptionalStr: typing_extensions.TypeAlias = typing.Optional[str] +5 6 | Foo = Literal["foo"] +6 7 | IntOrStr = int | str +7 8 | AliasNone = None + +PYI026.pyi:5:1: PYI026 [*] Use `typing_extensions.TypeAlias` for type alias, e.g., `Foo: TypeAlias = Literal["foo"]` + | +3 | NewAny = Any +4 | OptionalStr = typing.Optional[str] +5 | Foo = Literal["foo"] + | ^^^ PYI026 +6 | IntOrStr = int | str +7 | AliasNone = None + | + = help: Add `TypeAlias` annotation + +ℹ Suggested fix +1 1 | from typing import Literal, Any + 2 |+import typing_extensions +2 3 | +3 4 | NewAny = Any +4 5 | OptionalStr = typing.Optional[str] +5 |-Foo = Literal["foo"] + 6 |+Foo: typing_extensions.TypeAlias = Literal["foo"] +6 7 | IntOrStr = int | str +7 8 | AliasNone = None +8 9 | + +PYI026.pyi:6:1: PYI026 [*] Use `typing_extensions.TypeAlias` for type alias, e.g., `IntOrStr: TypeAlias = int | str` + | +4 | OptionalStr = typing.Optional[str] +5 | Foo = Literal["foo"] +6 | IntOrStr = int | str + | ^^^^^^^^ PYI026 +7 | AliasNone = None + | + = help: Add `TypeAlias` annotation + +ℹ Suggested fix +1 1 | from typing import Literal, Any + 2 |+import typing_extensions +2 3 | +3 4 | NewAny = Any +4 5 | OptionalStr = typing.Optional[str] +5 6 | Foo = Literal["foo"] +6 |-IntOrStr = int | str + 7 |+IntOrStr: typing_extensions.TypeAlias = int | str +7 8 | AliasNone = None +8 9 | +9 10 | NewAny: typing.TypeAlias = Any + +PYI026.pyi:7:1: PYI026 [*] Use `typing_extensions.TypeAlias` for type alias, e.g., `AliasNone: TypeAlias = None` + | +5 | Foo = Literal["foo"] +6 | IntOrStr = int | str +7 | AliasNone = None + | ^^^^^^^^^ PYI026 +8 | +9 | NewAny: typing.TypeAlias = Any + | + = help: Add `TypeAlias` annotation + +ℹ Suggested fix +1 1 | from typing import Literal, Any + 2 |+import typing_extensions +2 3 | +3 4 | NewAny = Any +4 5 | OptionalStr = typing.Optional[str] +5 6 | Foo = Literal["foo"] +6 7 | IntOrStr = int | str +7 |-AliasNone = None + 8 |+AliasNone: typing_extensions.TypeAlias = None +8 9 | +9 10 | NewAny: typing.TypeAlias = Any +10 11 | OptionalStr: TypeAlias = typing.Optional[str] + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/mod.rs b/crates/ruff/src/rules/flake8_pytest_style/mod.rs index c36222950e15c..fc73220c91d12 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/mod.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/mod.rs @@ -11,6 +11,7 @@ mod tests { use test_case::test_case; use crate::registry::Rule; + use crate::settings::types::IdentifierPattern; use crate::test::test_path; use crate::{assert_messages, settings}; @@ -143,7 +144,7 @@ mod tests { Rule::PytestRaisesTooBroad, Path::new("PT011.py"), Settings { - raises_extend_require_match_for: vec!["ZeroDivisionError".to_string()], + raises_extend_require_match_for: vec![IdentifierPattern::new("ZeroDivisionError").unwrap()], ..Settings::default() }, "PT011_extend_broad_exceptions" @@ -152,11 +153,29 @@ mod tests { Rule::PytestRaisesTooBroad, Path::new("PT011.py"), Settings { - raises_require_match_for: vec!["ZeroDivisionError".to_string()], + raises_require_match_for: vec![IdentifierPattern::new("ZeroDivisionError").unwrap()], ..Settings::default() }, "PT011_replace_broad_exceptions" )] + #[test_case( + Rule::PytestRaisesTooBroad, + Path::new("PT011.py"), + Settings { + raises_require_match_for: vec![IdentifierPattern::new("*").unwrap()], + ..Settings::default() + }, + "PT011_glob_all" + )] + #[test_case( + Rule::PytestRaisesTooBroad, + Path::new("PT011.py"), + Settings { + raises_require_match_for: vec![IdentifierPattern::new("pickle.*").unwrap()], + ..Settings::default() + }, + "PT011_glob_prefix" + )] #[test_case( Rule::PytestRaisesWithMultipleStatements, Path::new("PT012.py"), @@ -169,6 +188,12 @@ mod tests { Settings::default(), "PT013" )] + #[test_case( + Rule::PytestDuplicateParametrizeTestCases, + Path::new("PT014.py"), + Settings::default(), + "PT014" + )] #[test_case( Rule::PytestAssertAlwaysFalse, Path::new("PT015.py"), @@ -250,6 +275,18 @@ mod tests { Settings::default(), "PT026" )] + #[test_case( + Rule::PytestUnittestRaisesAssertion, + Path::new("PT027_0.py"), + Settings::default(), + "PT027_0" + )] + #[test_case( + Rule::PytestUnittestRaisesAssertion, + Path::new("PT027_1.py"), + Settings::default(), + "PT027_1" + )] fn test_pytest_style( rule_code: Rule, path: &Path, diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 552f902078388..0201096a05b58 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -1,18 +1,20 @@ use std::borrow::Cow; -use anyhow::bail; use anyhow::Result; +use anyhow::{bail, Context}; use libcst_native::{ self, Assert, BooleanOp, CompoundStatement, Expression, ParenthesizableWhitespace, ParenthesizedNode, SimpleStatementLine, SimpleWhitespace, SmallStatement, Statement, TrailingWhitespace, UnaryOperation, }; -use ruff_python_ast::{self as ast, BoolOp, ExceptHandler, Expr, Keyword, Ranged, Stmt, UnaryOp}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::Truthiness; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::{ + self as ast, Arguments, BoolOp, ExceptHandler, Expr, Keyword, Ranged, Stmt, UnaryOp, +}; use ruff_python_ast::{visitor, whitespace}; use ruff_python_codegen::Stylist; use ruff_source_file::Locator; @@ -21,6 +23,7 @@ use crate::autofix::codemods::CodegenStylist; use crate::checkers::ast::Checker; use crate::cst::matchers::match_indented_block; use crate::cst::matchers::match_module; +use crate::importer::ImportRequest; use crate::registry::AsRule; use super::unittest_assert::UnittestAssert; @@ -89,6 +92,9 @@ impl Violation for PytestCompositeAssertion { /// /// Use instead: /// ```python +/// import pytest +/// +/// /// def test_foo(): /// with pytest.raises(ZeroDivisionError) as exc_info: /// 1 / 0 @@ -112,6 +118,32 @@ impl Violation for PytestAssertInExcept { } } +/// ## What it does +/// Checks for `assert` statements whose test expression is a falsy value. +/// +/// ## Why is this bad? +/// `pytest.fail` conveys the intent more clearly than `assert falsy_value`. +/// +/// ## Example +/// ```python +/// def test_foo(): +/// if some_condition: +/// assert False, "some_condition was True" +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// def test_foo(): +/// if some_condition: +/// pytest.fail("some_condition was True") +/// ... +/// ``` +/// +/// References +/// - [`pytest` documentation: `pytest.fail`](https://docs.pytest.org/en/latest/reference/reference.html#pytest-fail) #[violation] pub struct PytestAssertAlwaysFalse; @@ -122,6 +154,36 @@ impl Violation for PytestAssertAlwaysFalse { } } +/// ## What it does +/// Checks for uses of assertion methods from the `unittest` module. +/// +/// ## Why is this bad? +/// To make use of `pytest`'s assertion rewriting, a regular `assert` statement +/// is preferred over `unittest`'s assertion methods. +/// +/// ## Example +/// ```python +/// import unittest +/// +/// +/// class TestFoo(unittest.TestCase): +/// def test_foo(self): +/// self.assertEqual(a, b) +/// ``` +/// +/// Use instead: +/// ```python +/// import unittest +/// +/// +/// class TestFoo(unittest.TestCase): +/// def test_foo(self): +/// assert a == b +/// ``` +/// +/// ## References +/// - [`pytest` documentation: Assertion introspection details](https://docs.pytest.org/en/7.1.x/how-to/assert.html#assertion-introspection-details) + #[violation] pub struct PytestUnittestAssertion { assertion: String, @@ -223,9 +285,8 @@ pub(crate) fn unittest_assertion( if checker.patch(diagnostic.kind.rule()) { // We're converting an expression to a statement, so avoid applying the fix if // the assertion is part of a larger expression. - if checker.semantic().stmt().is_expr_stmt() - && checker.semantic().expr_parent().is_none() - && !checker.semantic().scope().kind.is_lambda() + if checker.semantic().current_statement().is_expr_stmt() + && checker.semantic().current_expression_parent().is_none() && !checker.indexer().comment_ranges().intersects(expr.range()) { if let Ok(stmt) = unittest_assert.generate_assert(args, keywords) { @@ -245,6 +306,186 @@ pub(crate) fn unittest_assertion( } } +/// ## What it does +/// Checks for uses of exception-related assertion methods from the `unittest` +/// module. +/// +/// ## Why is this bad? +/// To enforce the assertion style recommended by `pytest`, `pytest.raises` is +/// preferred over the exception-related assertion methods in `unittest`, like +/// `assertRaises`. +/// +/// ## Example +/// ```python +/// import unittest +/// +/// +/// class TestFoo(unittest.TestCase): +/// def test_foo(self): +/// with self.assertRaises(ValueError): +/// raise ValueError("foo") +/// ``` +/// +/// Use instead: +/// ```python +/// import unittest +/// import pytest +/// +/// +/// class TestFoo(unittest.TestCase): +/// def test_foo(self): +/// with pytest.raises(ValueError): +/// raise ValueError("foo") +/// ``` +/// +/// ## References +/// - [`pytest` documentation: Assertions about expected exceptions](https://docs.pytest.org/en/latest/how-to/assert.html#assertions-about-expected-exceptions) +#[violation] +pub struct PytestUnittestRaisesAssertion { + assertion: String, +} + +impl Violation for PytestUnittestRaisesAssertion { + const AUTOFIX: AutofixKind = AutofixKind::Sometimes; + + #[derive_message_formats] + fn message(&self) -> String { + let PytestUnittestRaisesAssertion { assertion } = self; + format!("Use `pytest.raises` instead of unittest-style `{assertion}`") + } + + fn autofix_title(&self) -> Option { + let PytestUnittestRaisesAssertion { assertion } = self; + Some(format!("Replace `{assertion}` with `pytest.raises`")) + } +} + +/// PT027 +pub(crate) fn unittest_raises_assertion( + checker: &Checker, + call: &ast::ExprCall, +) -> Option { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = call.func.as_ref() else { + return None; + }; + + if !matches!( + attr.as_str(), + "assertRaises" | "failUnlessRaises" | "assertRaisesRegex" | "assertRaisesRegexp" + ) { + return None; + } + + let mut diagnostic = Diagnostic::new( + PytestUnittestRaisesAssertion { + assertion: attr.to_string(), + }, + call.func.range(), + ); + if checker.patch(diagnostic.kind.rule()) + && !checker.indexer().has_comments(call, checker.locator()) + { + if let Some(args) = to_pytest_raises_args(checker, attr.as_str(), &call.arguments) { + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("pytest", "raises"), + call.func.start(), + checker.semantic(), + )?; + let edit = Edit::range_replacement(format!("{binding}({args})"), call.range()); + Ok(Fix::suggested_edits(import_edit, [edit])) + }); + } + } + + Some(diagnostic) +} + +fn to_pytest_raises_args<'a>( + checker: &Checker<'a>, + attr: &str, + arguments: &Arguments, +) -> Option> { + let args = match attr { + "assertRaises" | "failUnlessRaises" => { + match (arguments.args.as_slice(), arguments.keywords.as_slice()) { + // Ex) `assertRaises(Exception)` + ([arg], []) => Cow::Borrowed(checker.locator().slice(arg.range())), + // Ex) `assertRaises(expected_exception=Exception)` + ([], [kwarg]) + if kwarg + .arg + .as_ref() + .is_some_and(|id| id.as_str() == "expected_exception") => + { + Cow::Borrowed(checker.locator().slice(kwarg.value.range())) + } + _ => return None, + } + } + "assertRaisesRegex" | "assertRaisesRegexp" => { + match (arguments.args.as_slice(), arguments.keywords.as_slice()) { + // Ex) `assertRaisesRegex(Exception, regex)` + ([arg1, arg2], []) => Cow::Owned(format!( + "{}, match={}", + checker.locator().slice(arg1.range()), + checker.locator().slice(arg2.range()) + )), + // Ex) `assertRaisesRegex(Exception, expected_regex=regex)` + ([arg], [kwarg]) + if kwarg + .arg + .as_ref() + .is_some_and(|arg| arg.as_str() == "expected_regex") => + { + Cow::Owned(format!( + "{}, match={}", + checker.locator().slice(arg.range()), + checker.locator().slice(kwarg.value.range()) + )) + } + // Ex) `assertRaisesRegex(expected_exception=Exception, expected_regex=regex)` + ([], [kwarg1, kwarg2]) + if kwarg1 + .arg + .as_ref() + .is_some_and(|id| id.as_str() == "expected_exception") + && kwarg2 + .arg + .as_ref() + .is_some_and(|id| id.as_str() == "expected_regex") => + { + Cow::Owned(format!( + "{}, match={}", + checker.locator().slice(kwarg1.value.range()), + checker.locator().slice(kwarg2.value.range()) + )) + } + // Ex) `assertRaisesRegex(expected_regex=regex, expected_exception=Exception)` + ([], [kwarg1, kwarg2]) + if kwarg1 + .arg + .as_ref() + .is_some_and(|id| id.as_str() == "expected_regex") + && kwarg2 + .arg + .as_ref() + .is_some_and(|id| id.as_str() == "expected_exception") => + { + Cow::Owned(format!( + "{}, match={}", + checker.locator().slice(kwarg2.value.range()), + checker.locator().slice(kwarg1.value.range()) + )) + } + _ => return None, + } + } + _ => return None, + }; + Some(args) +} + /// PT015 pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) { if Truthiness::from_expr(test, |id| checker.semantic().is_builtin(id)).is_falsey() { @@ -394,9 +635,8 @@ fn parenthesize<'a>(expression: Expression<'a>, parent: &Expression<'a>) -> Expr /// `assert a == "hello"` and `assert b == "world"`. fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> Result { // Infer the indentation of the outer block. - let Some(outer_indent) = whitespace::indentation(locator, stmt) else { - bail!("Unable to fix multiline statement"); - }; + let outer_indent = + whitespace::indentation(locator, stmt).context("Unable to fix multiline statement")?; // Extract the module text. let contents = locator.lines(stmt.range()); @@ -431,11 +671,11 @@ fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> &mut indented_block.body }; - let [Statement::Simple(simple_statement_line)] = &statements[..] else { + let [Statement::Simple(simple_statement_line)] = statements.as_slice() else { bail!("Expected one simple statement") }; - let [SmallStatement::Assert(assert_statement)] = &simple_statement_line.body[..] else { + let [SmallStatement::Assert(assert_statement)] = simple_statement_line.body.as_slice() else { bail!("Expected simple statement to be an assert") }; @@ -513,10 +753,13 @@ pub(crate) fn composite_condition( if matches!(composite, CompositionKind::Simple) && msg.is_none() && !checker.indexer().comment_ranges().intersects(stmt.range()) + && !checker + .indexer() + .in_multi_statement_line(stmt, checker.locator()) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { fix_composite_condition(stmt, checker.locator(), checker.stylist()) + .map(Fix::suggested) }); } } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs index ff749bb1e6f1f..6f469d9bf6c98 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::CallArguments; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -56,26 +54,25 @@ impl Violation for PytestFailWithoutMessage { } } -pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { - if is_pytest_fail(func, checker.semantic()) { - let call_args = CallArguments::new(args, keywords); - +pub(crate) fn fail_call(checker: &mut Checker, call: &ast::ExprCall) { + if is_pytest_fail(&call.func, checker.semantic()) { // Allow either `pytest.fail(reason="...")` (introduced in pytest 7.0) or // `pytest.fail(msg="...")` (deprecated in pytest 7.0) - let msg = call_args - .argument("reason", 0) - .or_else(|| call_args.argument("msg", 0)); + let msg = call + .arguments + .find_argument("reason", 0) + .or_else(|| call.arguments.find_argument("msg", 0)); if let Some(msg) = msg { if is_empty_or_null_string(msg) { checker .diagnostics - .push(Diagnostic::new(PytestFailWithoutMessage, func.range())); + .push(Diagnostic::new(PytestFailWithoutMessage, call.func.range())); } } else { checker .diagnostics - .push(Diagnostic::new(PytestFailWithoutMessage, func.range())); + .push(Diagnostic::new(PytestFailWithoutMessage, call.func.range())); } } } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs index e020008f630cd..0e2ec919a8b32 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs @@ -1,21 +1,19 @@ use std::fmt; -use ruff_python_ast::Decorator; -use ruff_python_ast::{self as ast, ArgWithDefault, Arguments, Expr, Ranged, Stmt}; -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::collect_call_path; -use ruff_python_ast::helpers::{find_keyword, includes_arg_name}; use ruff_python_ast::identifier::Identifier; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::Decorator; +use ruff_python_ast::{self as ast, Expr, ParameterWithDefault, Parameters, Ranged, Stmt}; use ruff_python_semantic::analyze::visibility::is_abstract; use ruff_python_semantic::SemanticModel; +use ruff_text_size::{TextLen, TextRange}; -use crate::autofix::edits::remove_argument; +use crate::autofix::edits; use crate::checkers::ast::Checker; use crate::registry::{AsRule, Rule}; @@ -24,7 +22,7 @@ use super::helpers::{ }; /// ## What it does -/// Checks for parameter-free `@pytest.fixture()` decorators with or without +/// Checks for argument-free `@pytest.fixture()` decorators with or without /// parentheses, depending on the `flake8-pytest-style.fixture-parentheses` /// setting. /// @@ -37,6 +35,9 @@ use super::helpers::{ /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.fixture /// def my_fixture(): /// ... @@ -44,6 +45,9 @@ use super::helpers::{ /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// def my_fixture(): /// ... @@ -76,6 +80,35 @@ impl AlwaysAutofixableViolation for PytestFixtureIncorrectParenthesesStyle { } } +/// ## What it does +/// Checks for `pytest.fixture` calls with positional arguments. +/// +/// ## Why is this bad? +/// For clarity and consistency, prefer using keyword arguments to specify +/// fixture configuration. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture("module") +/// def my_fixture(): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture(scope="module") +/// def my_fixture(): +/// ... +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `@pytest.fixture` functions](https://docs.pytest.org/en/latest/reference/reference.html#pytest-fixture) #[violation] pub struct PytestFixturePositionalArgs { function: String, @@ -89,6 +122,34 @@ impl Violation for PytestFixturePositionalArgs { } } +/// ## What it does +/// Checks for `pytest.fixture` calls with `scope="function"`. +/// +/// ## Why is this bad? +/// `scope="function"` can be omitted, as it is the default. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture(scope="function") +/// def my_fixture(): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def my_fixture(): +/// ... +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `@pytest.fixture` functions](https://docs.pytest.org/en/latest/reference/reference.html#pytest-fixture) #[violation] pub struct PytestExtraneousScopeFunction; @@ -103,6 +164,50 @@ impl AlwaysAutofixableViolation for PytestExtraneousScopeFunction { } } +/// ## What it does +/// Checks for `pytest` fixtures that do not return a value, but are not named +/// with a leading underscore. +/// +/// ## Why is this bad? +/// By convention, fixtures that don't return a value should be named with a +/// leading underscore, while fixtures that do return a value should not. +/// +/// This rule ignores abstract fixtures and generators. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def patch_something(mocker): +/// mocker.patch("module.object") +/// +/// +/// @pytest.fixture() +/// def use_context(): +/// with create_context(): +/// yield +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def _patch_something(mocker): +/// mocker.patch("module.object") +/// +/// +/// @pytest.fixture() +/// def _use_context(): +/// with create_context(): +/// yield +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `@pytest.fixture` functions](https://docs.pytest.org/en/latest/reference/reference.html#pytest-fixture) #[violation] pub struct PytestMissingFixtureNameUnderscore { function: String, @@ -116,6 +221,52 @@ impl Violation for PytestMissingFixtureNameUnderscore { } } +/// ## What it does +/// Checks for `pytest` fixtures that return a value, but are named with a +/// leading underscore. +/// +/// ## Why is this bad? +/// By convention, fixtures that don't return a value should be named with a +/// leading underscore, while fixtures that do return a value should not. +/// +/// This rule ignores abstract fixtures. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def _some_object(): +/// return SomeClass() +/// +/// +/// @pytest.fixture() +/// def _some_object_with_cleanup(): +/// obj = SomeClass() +/// yield obj +/// obj.cleanup() +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def some_object(): +/// return SomeClass() +/// +/// +/// @pytest.fixture() +/// def some_object_with_cleanup(): +/// obj = SomeClass() +/// yield obj +/// obj.cleanup() +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `@pytest.fixture` functions](https://docs.pytest.org/en/latest/reference/reference.html#pytest-fixture) #[violation] pub struct PytestIncorrectFixtureNameUnderscore { function: String, @@ -147,6 +298,9 @@ impl Violation for PytestIncorrectFixtureNameUnderscore { /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.fixture /// def _patch_something(): /// ... @@ -158,6 +312,9 @@ impl Violation for PytestIncorrectFixtureNameUnderscore { /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.fixture /// def _patch_something(): /// ... @@ -241,6 +398,9 @@ impl Violation for PytestDeprecatedYieldFixture { /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// def my_fixture(request): /// resource = acquire_resource() @@ -250,6 +410,9 @@ impl Violation for PytestDeprecatedYieldFixture { /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// def my_fixture(): /// resource = acquire_resource() @@ -290,6 +453,9 @@ impl Violation for PytestFixtureFinalizerCallback { /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// def my_fixture(): /// resource = acquire_resource() @@ -298,6 +464,9 @@ impl Violation for PytestFixtureFinalizerCallback { /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// def my_fixture_with_teardown(): /// resource = acquire_resource() @@ -330,6 +499,46 @@ impl AlwaysAutofixableViolation for PytestUselessYieldFixture { } } +/// ## What it does +/// Checks for `pytest.mark.usefixtures` decorators applied to `pytest` +/// fixtures. +/// +/// ## Why is this bad? +/// The `pytest.mark.usefixtures` decorator has no effect on `pytest` fixtures. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def a(): +/// pass +/// +/// +/// @pytest.mark.usefixtures("a") +/// @pytest.fixture() +/// def b(a): +/// pass +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.fixture() +/// def a(): +/// pass +/// +/// +/// @pytest.fixture() +/// def b(a): +/// pass +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `pytest.mark.usefixtures`](https://docs.pytest.org/en/latest/reference/reference.html#pytest-mark-usefixtures) #[violation] pub struct PytestErroneousUseFixturesOnFixture; @@ -352,6 +561,9 @@ impl AlwaysAutofixableViolation for PytestErroneousUseFixturesOnFixture { /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.mark.asyncio() /// @pytest.fixture() /// async def my_fixture(): @@ -360,6 +572,9 @@ impl AlwaysAutofixableViolation for PytestErroneousUseFixturesOnFixture { /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.fixture() /// async def my_fixture(): /// return 0 @@ -416,7 +631,7 @@ where self.has_return_with_value = true; } } - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => {} + Stmt::FunctionDef(_) => {} _ => visitor::walk_stmt(self, stmt), } } @@ -433,7 +648,7 @@ where } } Expr::Call(ast::ExprCall { func, .. }) => { - if collect_call_path(func).map_or(false, |call_path| { + if collect_call_path(func).is_some_and(|call_path| { matches!(call_path.as_slice(), ["request", "addfinalizer"]) }) { self.addfinalizer_call = Some(expr); @@ -476,14 +691,13 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &D match &decorator.expression { Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments, range: _, }) => { if checker.enabled(Rule::PytestFixtureIncorrectParenthesesStyle) { if !checker.settings.flake8_pytest_style.fixture_parentheses - && args.is_empty() - && keywords.is_empty() + && arguments.args.is_empty() + && arguments.keywords.is_empty() { let fix = Fix::automatic(Edit::deletion(func.end(), decorator.end())); pytest_fixture_parentheses( @@ -497,7 +711,7 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &D } if checker.enabled(Rule::PytestFixturePositionalArgs) { - if !args.is_empty() { + if !arguments.args.is_empty() { checker.diagnostics.push(Diagnostic::new( PytestFixturePositionalArgs { function: func_name.to_string(), @@ -508,19 +722,17 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &D } if checker.enabled(Rule::PytestExtraneousScopeFunction) { - if let Some(scope_keyword) = find_keyword(keywords, "scope") { - if keyword_is_literal(scope_keyword, "function") { + if let Some(keyword) = arguments.find_keyword("scope") { + if keyword_is_literal(keyword, "function") { let mut diagnostic = - Diagnostic::new(PytestExtraneousScopeFunction, scope_keyword.range()); + Diagnostic::new(PytestExtraneousScopeFunction, keyword.range()); if checker.patch(diagnostic.kind.rule()) { diagnostic.try_set_fix(|| { - remove_argument( - checker.locator(), - func.end(), - scope_keyword.range, - args, - keywords, - false, + edits::remove_argument( + keyword, + arguments, + edits::Parentheses::Preserve, + checker.locator().contents(), ) .map(Fix::suggested) }); @@ -607,25 +819,25 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: & } /// PT019 -fn check_test_function_args(checker: &mut Checker, arguments: &Arguments) { - arguments +fn check_test_function_args(checker: &mut Checker, parameters: &Parameters) { + parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) .for_each( - |ArgWithDefault { - def, + |ParameterWithDefault { + parameter, default: _, range: _, }| { - let name = &def.arg; + let name = ¶meter.name; if name.starts_with('_') { checker.diagnostics.push(Diagnostic::new( PytestFixtureParamWithoutValue { name: name.to_string(), }, - def.range(), + parameter.range(), )); } }, @@ -643,8 +855,8 @@ fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Decorator) { } /// PT021 -fn check_fixture_addfinalizer(checker: &mut Checker, args: &Arguments, body: &[Stmt]) { - if !includes_arg_name("request", args) { +fn check_fixture_addfinalizer(checker: &mut Checker, parameters: &Parameters, body: &[Stmt]) { + if !parameters.includes("request") { return; } @@ -696,7 +908,7 @@ pub(crate) fn fixture( checker: &mut Checker, stmt: &Stmt, name: &str, - args: &Arguments, + parameters: &Parameters, decorators: &[Decorator], body: &[Stmt], ) { @@ -724,7 +936,7 @@ pub(crate) fn fixture( } if checker.enabled(Rule::PytestFixtureFinalizerCallback) { - check_fixture_addfinalizer(checker, args, body); + check_fixture_addfinalizer(checker, parameters, body); } if checker.enabled(Rule::PytestUnnecessaryAsyncioMarkOnFixture) @@ -735,6 +947,6 @@ pub(crate) fn fixture( } if checker.enabled(Rule::PytestFixtureParamWithoutValue) && name.starts_with("test_") { - check_test_function_args(checker, args); + check_test_function_args(checker, parameters); } } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs index c2e99a19c1edd..43a183267fa78 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/helpers.rs @@ -21,42 +21,36 @@ pub(super) fn get_mark_decorators( } pub(super) fn is_pytest_fail(call: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(call).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "fail"]) - }) + semantic + .resolve_call_path(call) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "fail"])) } pub(super) fn is_pytest_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "fixture"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "fixture"])) } pub(super) fn is_pytest_yield_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "yield_fixture"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "yield_fixture"])) } pub(super) fn is_pytest_parametrize(decorator: &Decorator, semantic: &SemanticModel) -> bool { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "mark", "parametrize"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "mark", "parametrize"])) } pub(super) fn keyword_is_literal(keyword: &Keyword, literal: &str) -> bool { if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(string), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = &keyword.value { - string == literal + value == literal } else { false } @@ -69,7 +63,7 @@ pub(super) fn is_empty_or_null_string(expr: &Expr) -> bool { .. }) => string.is_empty(), Expr::Constant(constant) if constant.value.is_none() => true, - Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + Expr::FString(ast::ExprFString { values, .. }) => { values.iter().all(is_empty_or_null_string) } _ => false, diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs index 394af4ac30caf..3d689ce76522a 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/imports.rs @@ -3,6 +3,23 @@ use ruff_python_ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +/// ## What it does +/// Checks for incorrect import of pytest. +/// +/// ## Why is this bad? +/// `pytest` should be imported as `import pytest` and its members should be accessed in the form of +/// `pytest.xxx.yyy` for consistency and to make it easier for linting tools to analyze the code. +/// +/// ## Example +/// ```python +/// import pytest as pt +/// from pytest import fixture +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// ``` #[violation] pub struct PytestIncorrectPytestImport; diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs index 88d90b1f8891e..7a26b7ff2a1e7 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/marks.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Decorator, Expr, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -10,7 +10,7 @@ use crate::registry::{AsRule, Rule}; use super::helpers::get_mark_decorators; /// ## What it does -/// Checks for parameter-free `@pytest.mark.()` decorators with or +/// Checks for argument-free `@pytest.mark.()` decorators with or /// without parentheses, depending on the `flake8-pytest-style.mark-parentheses` /// setting. /// @@ -23,6 +23,9 @@ use super::helpers::get_mark_decorators; /// /// ## Example /// ```python +/// import pytest +/// +/// /// @pytest.mark.foo /// def test_something(): /// ... @@ -30,6 +33,9 @@ use super::helpers::get_mark_decorators; /// /// Use instead: /// ```python +/// import pytest +/// +/// /// @pytest.mark.foo() /// def test_something(): /// ... @@ -66,6 +72,33 @@ impl AlwaysAutofixableViolation for PytestIncorrectMarkParenthesesStyle { } } +/// ## What it does +/// Checks for `@pytest.mark.usefixtures()` decorators that aren't passed any +/// arguments. +/// +/// ## Why is this bad? +/// A `@pytest.mark.usefixtures()` decorator that isn't passed any arguments is +/// useless and should be removed. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.mark.usefixtures() +/// def test_something(): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// def test_something(): +/// ... +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `pytest.mark.usefixtures`](https://docs.pytest.org/en/latest/reference/reference.html#pytest-mark-usefixtures) + #[violation] pub struct PytestUseFixturesWithoutParameters; @@ -106,8 +139,12 @@ fn check_mark_parentheses(checker: &mut Checker, decorator: &Decorator, call_pat match &decorator.expression { Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) => { if !checker.settings.flake8_pytest_style.mark_parentheses @@ -134,7 +171,11 @@ fn check_useless_usefixtures(checker: &mut Checker, decorator: &Decorator, call_ let mut has_parameters = false; - if let Expr::Call(ast::ExprCall { args, keywords, .. }) = &decorator.expression { + if let Expr::Call(ast::ExprCall { + arguments: Arguments { args, keywords, .. }, + .. + }) = &decorator.expression + { if !args.is_empty() || !keywords.is_empty() { has_parameters = true; } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs index b1283c1b35a14..d262bc5142541 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -1,11 +1,16 @@ -use ruff_python_ast::{self as ast, Constant, Decorator, Expr, ExprContext, Ranged}; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::TextRange; +use std::hash::BuildHasherDefault; + +use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::comparable::ComparableExpr; +use ruff_python_ast::node::AstNode; +use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::{self as ast, Arguments, Constant, Decorator, Expr, ExprContext, Ranged}; use ruff_python_codegen::Generator; -use ruff_source_file::Locator; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::{TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::registry::{AsRule, Rule}; @@ -13,9 +18,61 @@ use crate::registry::{AsRule, Rule}; use super::super::types; use super::helpers::{is_pytest_parametrize, split_names}; +/// ## What it does +/// Checks for the type of parameter names passed to `pytest.mark.parametrize`. +/// +/// ## Why is this bad? +/// The `argnames` argument of `pytest.mark.parametrize` takes a string or +/// a sequence of strings. For a single parameter, it's preferable to use a +/// string, and for multiple parameters, it's preferable to use the style +/// configured via the `flake8-pytest-style.parametrize-names-type` setting. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// # single parameter, always expecting string +/// @pytest.mark.parametrize(("param",), [1, 2, 3]) +/// def test_foo(param): +/// ... +/// +/// +/// # multiple parameters, expecting tuple +/// @pytest.mark.parametrize(["param1", "param2"], [(1, 2), (3, 4)]) +/// def test_bar(param1, param2): +/// ... +/// +/// +/// # multiple parameters, expecting tuple +/// @pytest.mark.parametrize("param1,param2", [(1, 2), (3, 4)]) +/// def test_baz(param1, param2): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.mark.parametrize("param", [1, 2, 3]) +/// def test_foo(param): +/// ... +/// +/// +/// @pytest.mark.parametrize(("param1", "param2"), [(1, 2), (3, 4)]) +/// def test_bar(param1, param2): +/// ... +/// ``` +/// +/// ## Options +/// - `flake8-pytest-style.parametrize-names-type` +/// +/// ## References +/// - [`pytest` documentation: How to parametrize fixtures and test functions](https://docs.pytest.org/en/latest/how-to/parametrize.html#pytest-mark-parametrize) #[violation] pub struct PytestParametrizeNamesWrongType { - pub expected: types::ParametrizeNameType, + expected: types::ParametrizeNameType, } impl Violation for PytestParametrizeNamesWrongType { @@ -33,10 +90,75 @@ impl Violation for PytestParametrizeNamesWrongType { } } +/// ## What it does +/// Checks for the type of parameter values passed to `pytest.mark.parametrize`. +/// +/// ## Why is this bad? +/// The `argvalues` argument of `pytest.mark.parametrize` takes an iterator of +/// parameter values. For a single parameter, it's preferable to use a list, +/// and for multiple parameters, it's preferable to use a list of rows with +/// the type configured via the `flake8-pytest-style.parametrize-values-row-type` +/// setting. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// # expected list, got tuple +/// @pytest.mark.parametrize("param", (1, 2)) +/// def test_foo(param): +/// ... +/// +/// +/// # expected top-level list, got tuple +/// @pytest.mark.parametrize( +/// ("param1", "param2"), +/// ( +/// (1, 2), +/// (3, 4), +/// ), +/// ) +/// def test_bar(param1, param2): +/// ... +/// +/// +/// # expected individual rows to be tuples, got lists +/// @pytest.mark.parametrize( +/// ("param1", "param2"), +/// [ +/// [1, 2], +/// [3, 4], +/// ], +/// ) +/// def test_baz(param1, param2): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.mark.parametrize("param", [1, 2, 3]) +/// def test_foo(param): +/// ... +/// +/// +/// @pytest.mark.parametrize(("param1", "param2"), [(1, 2), (3, 4)]) +/// def test_bar(param1, param2): +/// ... +/// ``` +/// +/// ## Options +/// - `flake8-pytest-style.parametrize-values-row-type` +/// +/// ## References +/// - [`pytest` documentation: How to parametrize fixtures and test functions](https://docs.pytest.org/en/latest/how-to/parametrize.html#pytest-mark-parametrize) #[violation] pub struct PytestParametrizeValuesWrongType { - pub values: types::ParametrizeValuesType, - pub row: types::ParametrizeValuesRowType, + values: types::ParametrizeValuesType, + row: types::ParametrizeValuesRowType, } impl Violation for PytestParametrizeValuesWrongType { @@ -47,10 +169,68 @@ impl Violation for PytestParametrizeValuesWrongType { } } +/// ## What it does +/// Checks for duplicate test cases in `pytest.mark.parametrize`. +/// +/// ## Why is this bad? +/// Duplicate test cases are redundant and should be removed. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// @pytest.mark.parametrize( +/// ("param1", "param2"), +/// [ +/// (1, 2), +/// (1, 2), +/// ], +/// ) +/// def test_foo(param1, param2): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// @pytest.mark.parametrize( +/// ("param1", "param2"), +/// [ +/// (1, 2), +/// ], +/// ) +/// def test_foo(param1, param2): +/// ... +/// ``` +/// +/// ## References +/// - [`pytest` documentation: How to parametrize fixtures and test functions](https://docs.pytest.org/en/latest/how-to/parametrize.html#pytest-mark-parametrize) +#[violation] +pub struct PytestDuplicateParametrizeTestCases { + index: usize, +} + +impl Violation for PytestDuplicateParametrizeTestCases { + const AUTOFIX: AutofixKind = AutofixKind::Sometimes; + + #[derive_message_formats] + fn message(&self) -> String { + let PytestDuplicateParametrizeTestCases { index } = self; + format!("Duplicate of test case at index {index} in `@pytest_mark.parametrize`") + } + + fn autofix_title(&self) -> Option { + Some("Remove duplicate test case".to_string()) + } +} + fn elts_to_csv(elts: &[Expr], generator: Generator) -> Option { - let all_literals = elts.iter().all(|e| { + let all_literals = elts.iter().all(|expr| { matches!( - e, + expr, Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. @@ -63,19 +243,23 @@ fn elts_to_csv(elts: &[Expr], generator: Generator) -> Option { } let node = Expr::Constant(ast::ExprConstant { - value: Constant::Str(elts.iter().fold(String::new(), |mut acc, elt| { - if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(ref s), - .. - }) = elt - { - if !acc.is_empty() { - acc.push(','); + value: elts + .iter() + .fold(String::new(), |mut acc, elt| { + if let Expr::Constant(ast::ExprConstant { + value: Constant::Str(ast::StringConstant { value, .. }), + .. + }) = elt + { + if !acc.is_empty() { + acc.push(','); + } + acc.push_str(value.as_str()); } - acc.push_str(s); - } - acc - })), + acc + }) + .into(), + kind: None, range: TextRange::default(), }); @@ -84,48 +268,25 @@ fn elts_to_csv(elts: &[Expr], generator: Generator) -> Option { /// Returns the range of the `name` argument of `@pytest.mark.parametrize`. /// -/// This accounts for implicit string concatenation with parenthesis. -/// For example, the following code will return the range marked with `^`: +/// This accounts for parenthesized expressions. For example, the following code +/// will return the range marked with `^`: /// ```python -/// @pytest.mark.parametrize(("a, " "b"), [(1, 2)]) -/// # ^^^^^^^^^^^ -/// # implicit string concatenation with parenthesis +/// @pytest.mark.parametrize(("x"), [(1, 2)]) +/// # ^^^^^ /// def test(a, b): /// ... /// ``` /// /// This method assumes that the first argument is a string. -fn get_parametrize_name_range(decorator: &Decorator, expr: &Expr, locator: &Locator) -> TextRange { - let mut locations = Vec::new(); - let mut implicit_concat = None; - - // The parenthesis are not part of the AST, so we need to tokenize the - // decorator to find them. - for (tok, range) in lexer::lex_starts_at( - locator.slice(decorator.range()), - Mode::Module, - decorator.start(), - ) - .flatten() - { - match tok { - Tok::Lpar => locations.push(range.start()), - Tok::Rpar => { - if let Some(start) = locations.pop() { - implicit_concat = Some(TextRange::new(start, range.end())); - } - } - // Stop after the first argument. - Tok::Comma => break, - _ => (), - } - } - - if let Some(range) = implicit_concat { - range - } else { - expr.range() - } +fn get_parametrize_name_range( + decorator: &Decorator, + expr: &Expr, + source: &str, +) -> Option { + decorator + .expression + .as_call_expr() + .and_then(|call| parenthesized_range(expr.into(), call.arguments.as_any_node_ref(), source)) } /// PT006 @@ -141,8 +302,12 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { if names.len() > 1 { match names_type { types::ParametrizeNameType::Tuple => { - let name_range = - get_parametrize_name_range(decorator, expr, checker.locator()); + let name_range = get_parametrize_name_range( + decorator, + expr, + checker.locator().contents(), + ) + .unwrap_or(expr.range()); let mut diagnostic = Diagnostic::new( PytestParametrizeNamesWrongType { expected: names_type, @@ -155,7 +320,7 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { .iter() .map(|name| { Expr::Constant(ast::ExprConstant { - value: Constant::Str((*name).to_string()), + value: (*name).to_string().into(), kind: None, range: TextRange::default(), }) @@ -172,8 +337,12 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { checker.diagnostics.push(diagnostic); } types::ParametrizeNameType::List => { - let name_range = - get_parametrize_name_range(decorator, expr, checker.locator()); + let name_range = get_parametrize_name_range( + decorator, + expr, + checker.locator().contents(), + ) + .unwrap_or(expr.range()); let mut diagnostic = Diagnostic::new( PytestParametrizeNamesWrongType { expected: names_type, @@ -186,7 +355,7 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { .iter() .map(|name| { Expr::Constant(ast::ExprConstant { - value: Constant::Str((*name).to_string()), + value: (*name).to_string().into(), kind: None, range: TextRange::default(), }) @@ -336,6 +505,7 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) { values.range(), )); } + if is_multi_named { handle_value_rows(checker, elts, values_type, values_row_type); } @@ -358,6 +528,65 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) { } } +/// Given an element in a list, return the comma that follows it: +/// ```python +/// @pytest.mark.parametrize( +/// "x", +/// [.., (elt), ..], +/// ^^^^^ +/// Tokenize this range to locate the comma. +/// ) +/// ``` +fn trailing_comma(element: &Expr, source: &str) -> Option { + SimpleTokenizer::starts_at(element.end(), source) + .find(|token| token.kind == SimpleTokenKind::Comma) + .map(|token| token.start()) +} + +/// PT014 +fn check_duplicates(checker: &mut Checker, values: &Expr) { + let (Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. })) = + values + else { + return; + }; + + let mut seen: FxHashMap = + FxHashMap::with_capacity_and_hasher(elts.len(), BuildHasherDefault::default()); + let mut prev = None; + for (index, element) in elts.iter().enumerate() { + let expr = ComparableExpr::from(element); + seen.entry(expr) + .and_modify(|index| { + let mut diagnostic = Diagnostic::new( + PytestDuplicateParametrizeTestCases { index: *index }, + element.range(), + ); + if checker.patch(diagnostic.kind.rule()) { + if let Some(prev) = prev { + let values_end = values.range().end() - TextSize::new(1); + let previous_end = trailing_comma(prev, checker.locator().contents()) + .unwrap_or(values_end); + let element_end = trailing_comma(element, checker.locator().contents()) + .unwrap_or(values_end); + let deletion_range = TextRange::new(previous_end, element_end); + if !checker + .indexer() + .comment_ranges() + .intersects(deletion_range) + { + diagnostic + .set_fix(Fix::suggested(Edit::range_deletion(deletion_range))); + } + } + } + checker.diagnostics.push(diagnostic); + }) + .or_insert(index); + prev = Some(element); + } +} + fn handle_single_name(checker: &mut Checker, expr: &Expr, value: &Expr) { let mut diagnostic = Diagnostic::new( PytestParametrizeNamesWrongType { @@ -414,17 +643,24 @@ fn handle_value_rows( pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Decorator]) { for decorator in decorators { if is_pytest_parametrize(decorator, checker.semantic()) { - if let Expr::Call(ast::ExprCall { args, .. }) = &decorator.expression { + if let Expr::Call(ast::ExprCall { + arguments: Arguments { args, .. }, + .. + }) = &decorator.expression + { if checker.enabled(Rule::PytestParametrizeNamesWrongType) { - if let Some(names) = args.get(0) { + if let [names, ..] = args.as_slice() { check_names(checker, decorator, names); } } if checker.enabled(Rule::PytestParametrizeValuesWrongType) { - if let Some(names) = args.get(0) { - if let Some(values) = args.get(1) { - check_values(checker, names, values); - } + if let [names, values, ..] = args.as_slice() { + check_values(checker, names, values); + } + } + if checker.enabled(Rule::PytestDuplicateParametrizeTestCases) { + if let [_, values, ..] = args.as_slice() { + check_duplicates(checker, values); } } } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs index 637f675b75275..229c13a28bbac 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/patch.rs @@ -1,12 +1,43 @@ -use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::collect_call_path; -use ruff_python_ast::helpers::{find_keyword, includes_arg_name, CallArguments}; use ruff_python_ast::visitor; use ruff_python_ast::visitor::Visitor; +use ruff_python_ast::{self as ast, Expr, Parameters, Ranged}; +/// ## What it does +/// Checks for mocked calls that use a dummy `lambda` function instead of +/// `return_value`. +/// +/// ## Why is this bad? +/// When patching calls, an explicit `return_value` better conveys the intent +/// than a `lambda` function, assuming the `lambda` does not use the arguments +/// passed to it. +/// +/// `return_value` is also robust to changes in the patched function's +/// signature, and enables additional assertions to verify behavior. For +/// example, `return_value` allows for verification of the number of calls or +/// the arguments passed to the patched function via `assert_called_once_with` +/// and related methods. +/// +/// ## Example +/// ```python +/// def test_foo(mocker): +/// mocker.patch("module.target", lambda x, y: 7) +/// ``` +/// +/// Use instead: +/// ```python +/// def test_foo(mocker): +/// mocker.patch("module.target", return_value=7) +/// +/// # If the lambda makes use of the arguments, no diagnostic is emitted. +/// mocker.patch("module.other_target", lambda x, y: x) +/// ``` +/// +/// ## References +/// - [Python documentation: `unittest.mock.patch`](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch) +/// - [`pytest-mock`](https://pypi.org/project/pytest-mock/) #[violation] pub struct PytestPatchWithLambda; @@ -20,7 +51,7 @@ impl Violation for PytestPatchWithLambda { /// Visitor that checks references the argument names in the lambda body. #[derive(Debug)] struct LambdaBodyVisitor<'a> { - arguments: &'a Arguments, + parameters: &'a Parameters, uses_args: bool, } @@ -31,7 +62,7 @@ where fn visit_expr(&mut self, expr: &'b Expr) { match expr { Expr::Name(ast::ExprName { id, .. }) => { - if includes_arg_name(id, self.arguments) { + if self.parameters.includes(id) { self.uses_args = true; } } @@ -44,44 +75,38 @@ where } } -fn check_patch_call( - call: &Expr, - args: &[Expr], - keywords: &[Keyword], - new_arg_number: usize, -) -> Option { - if find_keyword(keywords, "return_value").is_some() { +fn check_patch_call(call: &ast::ExprCall, index: usize) -> Option { + if call.arguments.find_keyword("return_value").is_some() { return None; } let ast::ExprLambda { - args, + parameters, body, range: _, - } = CallArguments::new(args, keywords) - .argument("new", new_arg_number)? + } = call + .arguments + .find_argument("new", index)? .as_lambda_expr()?; - // Walk the lambda body. - let mut visitor = LambdaBodyVisitor { - arguments: args, - uses_args: false, - }; - visitor.visit_expr(body); - - if visitor.uses_args { - None - } else { - Some(Diagnostic::new(PytestPatchWithLambda, call.range())) + // Walk the lambda body. If the lambda uses the arguments, then it's valid. + if let Some(parameters) = parameters { + let mut visitor = LambdaBodyVisitor { + parameters, + uses_args: false, + }; + visitor.visit_expr(body); + if visitor.uses_args { + return None; + } } + + Some(Diagnostic::new(PytestPatchWithLambda, call.func.range())) } -pub(crate) fn patch_with_lambda( - call: &Expr, - args: &[Expr], - keywords: &[Keyword], -) -> Option { - let call_path = collect_call_path(call)?; +/// PT008 +pub(crate) fn patch_with_lambda(call: &ast::ExprCall) -> Option { + let call_path = collect_call_path(&call.func)?; if matches!( call_path.as_slice(), @@ -95,7 +120,7 @@ pub(crate) fn patch_with_lambda( "patch" ] | ["unittest", "mock", "patch"] ) { - check_patch_call(call, args, keywords, 1) + check_patch_call(call, 1) } else if matches!( call_path.as_slice(), [ @@ -109,7 +134,7 @@ pub(crate) fn patch_with_lambda( "object" ] | ["unittest", "mock", "patch", "object"] ) { - check_patch_call(call, args, keywords, 2) + check_patch_call(call, 2) } else { None } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs index 46dc667596449..9510b294c7b14 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs @@ -1,10 +1,8 @@ -use ruff_python_ast::helpers::{find_keyword, is_compound_statement}; -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged, Stmt, WithItem}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::format_call_path; -use ruff_python_ast::call_path::from_qualified_name; +use ruff_python_ast::helpers::is_compound_statement; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt, WithItem}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -12,6 +10,41 @@ use crate::registry::Rule; use super::helpers::is_empty_or_null_string; +/// ## What it does +/// Checks for `pytest.raises` context managers with multiple statements. +/// +/// ## Why is this bad? +/// When a `pytest.raises` is used as a context manager and contains multiple +/// statements, it can lead to the test passing when it actually should fail. +/// To avoid this, a `pytest.raises` context manager should only contain +/// a single simple statement that raises the expected exception. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// def test_foo(): +/// with pytest.raises(MyError): +/// setup() # may raise `MyError` +/// func_to_test() +/// assert foo() # not executed +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// def test_foo(): +/// setup() +/// with pytest.raises(MyException): +/// func_to_test() +/// assert foo() +/// ``` +/// +/// ## References +/// - [`pytest` documentation: `pytest.raises`](https://docs.pytest.org/en/latest/reference/reference.html#pytest-raises) #[violation] pub struct PytestRaisesWithMultipleStatements; @@ -22,6 +55,47 @@ impl Violation for PytestRaisesWithMultipleStatements { } } +/// ## What it does +/// Checks for `pytest.raises` calls without a `match` parameter. +/// +/// ## Why is this bad? +/// `pytest.raises(Error)` will catch any `Error` and may catch errors that are +/// unrelated to the code under test. To avoid this, `pytest.raises` should be +/// called with a `match` parameter. The exception names that require a `match` +/// parameter can be configured via the +/// `flake8-pytest-style.raises-require-match-for` and +/// `flake8-pytest-style.raises-extend-require-match-for` settings. +/// +/// ## Example +/// ```python +/// import pytest +/// +/// +/// def test_foo(): +/// with pytest.raises(ValueError): +/// ... +/// +/// # empty string is also an error +/// with pytest.raises(ValueError, match=""): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// import pytest +/// +/// +/// def test_foo(): +/// with pytest.raises(ValueError, match="expected message"): +/// ... +/// ``` +/// +/// ## Options +/// - `flake8-pytest-style.raises-require-match-for` +/// - `flake8-pytest-style.raises-extend-require-match-for` +/// +/// ## References +/// - [`pytest` documentation: `pytest.raises`](https://docs.pytest.org/en/latest/reference/reference.html#pytest-raises) #[violation] pub struct PytestRaisesTooBroad { exception: String, @@ -78,9 +152,9 @@ impl Violation for PytestRaisesWithoutException { } fn is_pytest_raises(func: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(func).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pytest", "raises"]) - }) + semantic + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pytest", "raises"])) } const fn is_non_trivial_with_body(body: &[Stmt]) -> bool { @@ -91,19 +165,20 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool { } } -pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { - if is_pytest_raises(func, checker.semantic()) { +pub(crate) fn raises_call(checker: &mut Checker, call: &ast::ExprCall) { + if is_pytest_raises(&call.func, checker.semantic()) { if checker.enabled(Rule::PytestRaisesWithoutException) { - if args.is_empty() && keywords.is_empty() { - checker - .diagnostics - .push(Diagnostic::new(PytestRaisesWithoutException, func.range())); + if call.arguments.is_empty() { + checker.diagnostics.push(Diagnostic::new( + PytestRaisesWithoutException, + call.func.range(), + )); } } if checker.enabled(Rule::PytestRaisesTooBroad) { - let match_keyword = find_keyword(keywords, "match"); - if let Some(exception) = args.first() { + let match_keyword = call.arguments.find_keyword("match"); + if let Some(exception) = call.arguments.args.first() { if let Some(match_keyword) = match_keyword { if is_empty_or_null_string(&match_keyword.value) { exception_needs_match(checker, exception); @@ -131,12 +206,9 @@ pub(crate) fn complex_raises( if raises_called { let is_too_complex = if let [stmt] = body { match stmt { - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { - is_non_trivial_with_body(body) - } + Stmt::With(ast::StmtWith { body, .. }) => is_non_trivial_with_body(body), // Allow function and class definitions to test decorators - Stmt::ClassDef(_) | Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => false, + Stmt::ClassDef(_) | Stmt::FunctionDef(_) => false, stmt => is_compound_statement(stmt), } } else { @@ -158,7 +230,8 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .semantic() .resolve_call_path(exception) .and_then(|call_path| { - let is_broad_exception = checker + let call_path = format_call_path(&call_path); + checker .settings .flake8_pytest_style .raises_require_match_for @@ -169,12 +242,8 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .flake8_pytest_style .raises_extend_require_match_for, ) - .any(|target| call_path == from_qualified_name(target)); - if is_broad_exception { - Some(format_call_path(&call_path)) - } else { - None - } + .any(|pattern| pattern.matches(&call_path)) + .then_some(call_path) }) { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs index e929c9f8de522..49c78e10d49e8 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/unittest_assert.rs @@ -2,7 +2,7 @@ use std::hash::BuildHasherDefault; use anyhow::{anyhow, bail, Result}; use ruff_python_ast::{ - self as ast, CmpOp, Constant, Expr, ExprContext, Identifier, Keyword, Stmt, UnaryOp, + self as ast, Arguments, CmpOp, Constant, Expr, ExprContext, Identifier, Keyword, Stmt, UnaryOp, }; use ruff_text_size::TextRange; use rustc_hash::FxHashMap; @@ -19,6 +19,13 @@ pub(crate) enum UnittestAssert { DictEqual, Equal, Equals, + FailIf, + FailIfAlmostEqual, + FailIfEqual, + FailUnless, + FailUnlessAlmostEqual, + FailUnlessEqual, + // FailUnlessRaises, False, Greater, GreaterEqual, @@ -62,10 +69,16 @@ impl std::fmt::Display for UnittestAssert { UnittestAssert::AlmostEqual => write!(f, "assertAlmostEqual"), UnittestAssert::AlmostEquals => write!(f, "assertAlmostEquals"), UnittestAssert::CountEqual => write!(f, "assertCountEqual"), - UnittestAssert::DictEqual => write!(f, "assertDictEqual"), UnittestAssert::DictContainsSubset => write!(f, "assertDictContainsSubset"), + UnittestAssert::DictEqual => write!(f, "assertDictEqual"), UnittestAssert::Equal => write!(f, "assertEqual"), UnittestAssert::Equals => write!(f, "assertEquals"), + UnittestAssert::FailIf => write!(f, "failIf"), + UnittestAssert::FailIfAlmostEqual => write!(f, "failIfAlmostEqual"), + UnittestAssert::FailIfEqual => write!(f, "failIfEqual"), + UnittestAssert::FailUnless => write!(f, "failUnless"), + UnittestAssert::FailUnlessAlmostEqual => write!(f, "failUnlessAlmostEqual"), + UnittestAssert::FailUnlessEqual => write!(f, "failUnlessEqual"), UnittestAssert::False => write!(f, "assertFalse"), UnittestAssert::Greater => write!(f, "assertGreater"), UnittestAssert::GreaterEqual => write!(f, "assertGreaterEqual"), @@ -110,6 +123,12 @@ impl TryFrom<&str> for UnittestAssert { "assertDictEqual" => Ok(UnittestAssert::DictEqual), "assertEqual" => Ok(UnittestAssert::Equal), "assertEquals" => Ok(UnittestAssert::Equals), + "failIf" => Ok(UnittestAssert::FailIf), + "failIfAlmostEqual" => Ok(UnittestAssert::FailIfAlmostEqual), + "failIfEqual" => Ok(UnittestAssert::FailIfEqual), + "failUnless" => Ok(UnittestAssert::FailUnless), + "failUnlessAlmostEqual" => Ok(UnittestAssert::FailUnlessAlmostEqual), + "failUnlessEqual" => Ok(UnittestAssert::FailUnlessEqual), "assertFalse" => Ok(UnittestAssert::False), "assertGreater" => Ok(UnittestAssert::Greater), "assertGreaterEqual" => Ok(UnittestAssert::GreaterEqual), @@ -198,6 +217,12 @@ impl UnittestAssert { UnittestAssert::True => &["expr", "msg"], UnittestAssert::TupleEqual => &["first", "second", "msg"], UnittestAssert::Underscore => &["expr", "msg"], + UnittestAssert::FailIf => &["expr", "msg"], + UnittestAssert::FailIfAlmostEqual => &["first", "second", "msg"], + UnittestAssert::FailIfEqual => &["first", "second", "msg"], + UnittestAssert::FailUnless => &["expr", "msg"], + UnittestAssert::FailUnlessAlmostEqual => &["first", "second", "places", "msg", "delta"], + UnittestAssert::FailUnlessEqual => &["first", "second", "places", "msg", "delta"], } } @@ -218,7 +243,7 @@ impl UnittestAssert { if keywords.iter().any(|kw| { kw.arg .as_ref() - .map_or(false, |kwarg_name| !arg_spec.contains(&kwarg_name.as_str())) + .is_some_and(|kwarg_name| !arg_spec.contains(&kwarg_name.as_str())) }) { bail!("Unknown keyword argument"); } @@ -240,7 +265,7 @@ impl UnittestAssert { if keyword .arg .as_ref() - .map_or(false, |kwarg_name| &kwarg_name == arg_name) + .is_some_and(|kwarg_name| &kwarg_name == arg_name) { Some(&keyword.value) } else { @@ -257,28 +282,35 @@ impl UnittestAssert { pub(crate) fn generate_assert(self, args: &[Expr], keywords: &[Keyword]) -> Result { let args = self.args_map(args, keywords)?; match self { - UnittestAssert::True | UnittestAssert::False => { + UnittestAssert::True + | UnittestAssert::False + | UnittestAssert::FailUnless + | UnittestAssert::FailIf => { let expr = *args .get("expr") .ok_or_else(|| anyhow!("Missing argument `expr`"))?; let msg = args.get("msg").copied(); - Ok(if matches!(self, UnittestAssert::False) { - assert( - &Expr::UnaryOp(ast::ExprUnaryOp { - op: UnaryOp::Not, - operand: Box::new(expr.clone()), - range: TextRange::default(), - }), - msg, - ) - } else { - assert(expr, msg) - }) + Ok( + if matches!(self, UnittestAssert::False | UnittestAssert::FailIf) { + assert( + &Expr::UnaryOp(ast::ExprUnaryOp { + op: UnaryOp::Not, + operand: Box::new(expr.clone()), + range: TextRange::default(), + }), + msg, + ) + } else { + assert(expr, msg) + }, + ) } UnittestAssert::Equal | UnittestAssert::Equals + | UnittestAssert::FailUnlessEqual | UnittestAssert::NotEqual | UnittestAssert::NotEquals + | UnittestAssert::FailIfEqual | UnittestAssert::Greater | UnittestAssert::GreaterEqual | UnittestAssert::Less @@ -293,8 +325,12 @@ impl UnittestAssert { .ok_or_else(|| anyhow!("Missing argument `second`"))?; let msg = args.get("msg").copied(); let cmp_op = match self { - UnittestAssert::Equal | UnittestAssert::Equals => CmpOp::Eq, - UnittestAssert::NotEqual | UnittestAssert::NotEquals => CmpOp::NotEq, + UnittestAssert::Equal + | UnittestAssert::Equals + | UnittestAssert::FailUnlessEqual => CmpOp::Eq, + UnittestAssert::NotEqual + | UnittestAssert::NotEquals + | UnittestAssert::FailIfEqual => CmpOp::NotEq, UnittestAssert::Greater => CmpOp::Gt, UnittestAssert::GreaterEqual => CmpOp::GtE, UnittestAssert::Less => CmpOp::Lt, @@ -355,8 +391,11 @@ impl UnittestAssert { }; let node1 = ast::ExprCall { func: Box::new(node.into()), - args: vec![(**obj).clone(), (**cls).clone()], - keywords: vec![], + arguments: Arguments { + args: vec![(**obj).clone(), (**cls).clone()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let isinstance = node1.into(); @@ -396,8 +435,11 @@ impl UnittestAssert { }; let node2 = ast::ExprCall { func: Box::new(node1.into()), - args: vec![(**regex).clone(), (**text).clone()], - keywords: vec![], + arguments: Arguments { + args: vec![(**regex).clone(), (**text).clone()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let re_search = node2.into(); diff --git a/crates/ruff/src/rules/flake8_pytest_style/settings.rs b/crates/ruff/src/rules/flake8_pytest_style/settings.rs index d00a3d8ebcb1f..bbbbebc86f501 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/settings.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/settings.rs @@ -1,12 +1,15 @@ //! Settings for the `flake8-pytest-style` plugin. +use std::error::Error; +use std::fmt; use serde::{Deserialize, Serialize}; +use crate::settings::types::IdentifierPattern; use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions}; use super::types; -fn default_broad_exceptions() -> Vec { +fn default_broad_exceptions() -> Vec { [ "BaseException", "Exception", @@ -16,7 +19,7 @@ fn default_broad_exceptions() -> Vec { "EnvironmentError", "socket.error", ] - .map(ToString::to_string) + .map(|pattern| IdentifierPattern::new(pattern).expect("invalid default exception pattern")) .to_vec() } @@ -86,6 +89,9 @@ pub struct Options { )] /// List of exception names that require a match= parameter in a /// `pytest.raises()` call. + /// + /// Supports glob patterns. For more information on the glob syntax, refer + /// to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax). pub raises_require_match_for: Option>, #[option( default = "[]", @@ -100,6 +106,9 @@ pub struct Options { /// the entire list. /// Note that this option does not remove any exceptions from the default /// list. + /// + /// Supports glob patterns. For more information on the glob syntax, refer + /// to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax). pub raises_extend_require_match_for: Option>, #[option( default = "true", @@ -120,26 +129,44 @@ pub struct Settings { pub parametrize_names_type: types::ParametrizeNameType, pub parametrize_values_type: types::ParametrizeValuesType, pub parametrize_values_row_type: types::ParametrizeValuesRowType, - pub raises_require_match_for: Vec, - pub raises_extend_require_match_for: Vec, + pub raises_require_match_for: Vec, + pub raises_extend_require_match_for: Vec, pub mark_parentheses: bool, } -impl From for Settings { - fn from(options: Options) -> Self { - Self { +impl TryFrom for Settings { + type Error = SettingsError; + + fn try_from(options: Options) -> Result { + Ok(Self { fixture_parentheses: options.fixture_parentheses.unwrap_or(true), parametrize_names_type: options.parametrize_names_type.unwrap_or_default(), parametrize_values_type: options.parametrize_values_type.unwrap_or_default(), parametrize_values_row_type: options.parametrize_values_row_type.unwrap_or_default(), raises_require_match_for: options .raises_require_match_for + .map(|patterns| { + patterns + .into_iter() + .map(|pattern| IdentifierPattern::new(&pattern)) + .collect() + }) + .transpose() + .map_err(SettingsError::InvalidRaisesRequireMatchFor)? .unwrap_or_else(default_broad_exceptions), raises_extend_require_match_for: options .raises_extend_require_match_for + .map(|patterns| { + patterns + .into_iter() + .map(|pattern| IdentifierPattern::new(&pattern)) + .collect() + }) + .transpose() + .map_err(SettingsError::InvalidRaisesExtendRequireMatchFor)? .unwrap_or_default(), mark_parentheses: options.mark_parentheses.unwrap_or(true), - } + }) } } impl From for Options { @@ -149,8 +176,20 @@ impl From for Options { parametrize_names_type: Some(settings.parametrize_names_type), parametrize_values_type: Some(settings.parametrize_values_type), parametrize_values_row_type: Some(settings.parametrize_values_row_type), - raises_require_match_for: Some(settings.raises_require_match_for), - raises_extend_require_match_for: Some(settings.raises_extend_require_match_for), + raises_require_match_for: Some( + settings + .raises_require_match_for + .iter() + .map(ToString::to_string) + .collect(), + ), + raises_extend_require_match_for: Some( + settings + .raises_extend_require_match_for + .iter() + .map(ToString::to_string) + .collect(), + ), mark_parentheses: Some(settings.mark_parentheses), } } @@ -169,3 +208,32 @@ impl Default for Settings { } } } + +/// Error returned by the [`TryFrom`] implementation of [`Settings`]. +#[derive(Debug)] +pub enum SettingsError { + InvalidRaisesRequireMatchFor(glob::PatternError), + InvalidRaisesExtendRequireMatchFor(glob::PatternError), +} + +impl fmt::Display for SettingsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SettingsError::InvalidRaisesRequireMatchFor(err) => { + write!(f, "invalid raises-require-match-for pattern: {err}") + } + SettingsError::InvalidRaisesExtendRequireMatchFor(err) => { + write!(f, "invalid raises-extend-require-match-for pattern: {err}") + } + } + } +} + +impl Error for SettingsError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + SettingsError::InvalidRaisesRequireMatchFor(err) => Some(err), + SettingsError::InvalidRaisesExtendRequireMatchFor(err) => Some(err), + } + } +} diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_default.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_default.snap index 9ed5a819f45c3..26ada2a795a41 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_default.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_default.snap @@ -208,5 +208,24 @@ PT006.py:64:26: PT006 [*] Wrong name(s) type in `@pytest.mark.parametrize`, expe 64 |+@pytest.mark.parametrize(("param1", "param2", "param3"), [(1, 2, 3), (4, 5, 6)]) 65 65 | def test_implicit_str_concat_with_multi_parens(param1, param2, param3): 66 66 | ... +67 67 | + +PT006.py:69:26: PT006 [*] Wrong name(s) type in `@pytest.mark.parametrize`, expected `tuple` + | +69 | @pytest.mark.parametrize(("param1,param2"), [(1, 2), (3, 4)]) + | ^^^^^^^^^^^^^^^^^ PT006 +70 | def test_csv_with_parens(param1, param2): +71 | ... + | + = help: Use a `tuple` for parameter names + +ℹ Suggested fix +66 66 | ... +67 67 | +68 68 | +69 |-@pytest.mark.parametrize(("param1,param2"), [(1, 2), (3, 4)]) + 69 |+@pytest.mark.parametrize(("param1", "param2"), [(1, 2), (3, 4)]) +70 70 | def test_csv_with_parens(param1, param2): +71 71 | ... diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_list.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_list.snap index 3cd37fa141bbd..2d40708e9461a 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_list.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT006_list.snap @@ -170,5 +170,24 @@ PT006.py:64:26: PT006 [*] Wrong name(s) type in `@pytest.mark.parametrize`, expe 64 |+@pytest.mark.parametrize(["param1", "param2", "param3"], [(1, 2, 3), (4, 5, 6)]) 65 65 | def test_implicit_str_concat_with_multi_parens(param1, param2, param3): 66 66 | ... +67 67 | + +PT006.py:69:26: PT006 [*] Wrong name(s) type in `@pytest.mark.parametrize`, expected `list` + | +69 | @pytest.mark.parametrize(("param1,param2"), [(1, 2), (3, 4)]) + | ^^^^^^^^^^^^^^^^^ PT006 +70 | def test_csv_with_parens(param1, param2): +71 | ... + | + = help: Use a `list` for parameter names + +ℹ Suggested fix +66 66 | ... +67 67 | +68 68 | +69 |-@pytest.mark.parametrize(("param1,param2"), [(1, 2), (3, 4)]) + 69 |+@pytest.mark.parametrize(["param1", "param2"], [(1, 2), (3, 4)]) +70 70 | def test_csv_with_parens(param1, param2): +71 71 | ... diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap index be4c1bb726387..ff04ae6a491c8 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap @@ -548,6 +548,8 @@ PT009.py:82:9: PT009 [*] Use a regular `assert` instead of unittest-style `asser 81 | def test_assert_not_regexp_matches(self): 82 | self.assertNotRegex("abc", r"abc") # Error | ^^^^^^^^^^^^^^^^^^^ PT009 +83 | +84 | def test_fail_if(self): | = help: Replace `assertNotRegex(...)` with `assert ...` @@ -557,5 +559,83 @@ PT009.py:82:9: PT009 [*] Use a regular `assert` instead of unittest-style `asser 81 81 | def test_assert_not_regexp_matches(self): 82 |- self.assertNotRegex("abc", r"abc") # Error 82 |+ assert not re.search("abc", "abc") # Error +83 83 | +84 84 | def test_fail_if(self): +85 85 | self.failIf("abc") # Error + +PT009.py:85:9: PT009 [*] Use a regular `assert` instead of unittest-style `failIf` + | +84 | def test_fail_if(self): +85 | self.failIf("abc") # Error + | ^^^^^^^^^^^ PT009 +86 | +87 | def test_fail_unless(self): + | + = help: Replace `failIf(...)` with `assert ...` + +ℹ Suggested fix +82 82 | self.assertNotRegex("abc", r"abc") # Error +83 83 | +84 84 | def test_fail_if(self): +85 |- self.failIf("abc") # Error + 85 |+ assert not "abc" # Error +86 86 | +87 87 | def test_fail_unless(self): +88 88 | self.failUnless("abc") # Error + +PT009.py:88:9: PT009 [*] Use a regular `assert` instead of unittest-style `failUnless` + | +87 | def test_fail_unless(self): +88 | self.failUnless("abc") # Error + | ^^^^^^^^^^^^^^^ PT009 +89 | +90 | def test_fail_unless_equal(self): + | + = help: Replace `failUnless(...)` with `assert ...` + +ℹ Suggested fix +85 85 | self.failIf("abc") # Error +86 86 | +87 87 | def test_fail_unless(self): +88 |- self.failUnless("abc") # Error + 88 |+ assert "abc" # Error +89 89 | +90 90 | def test_fail_unless_equal(self): +91 91 | self.failUnlessEqual(1, 2) # Error + +PT009.py:91:9: PT009 [*] Use a regular `assert` instead of unittest-style `failUnlessEqual` + | +90 | def test_fail_unless_equal(self): +91 | self.failUnlessEqual(1, 2) # Error + | ^^^^^^^^^^^^^^^^^^^^ PT009 +92 | +93 | def test_fail_if_equal(self): + | + = help: Replace `failUnlessEqual(...)` with `assert ...` + +ℹ Suggested fix +88 88 | self.failUnless("abc") # Error +89 89 | +90 90 | def test_fail_unless_equal(self): +91 |- self.failUnlessEqual(1, 2) # Error + 91 |+ assert 1 == 2 # Error +92 92 | +93 93 | def test_fail_if_equal(self): +94 94 | self.failIfEqual(1, 2) # Error + +PT009.py:94:9: PT009 [*] Use a regular `assert` instead of unittest-style `failIfEqual` + | +93 | def test_fail_if_equal(self): +94 | self.failIfEqual(1, 2) # Error + | ^^^^^^^^^^^^^^^^ PT009 + | + = help: Replace `failIfEqual(...)` with `assert ...` + +ℹ Suggested fix +91 91 | self.failUnlessEqual(1, 2) # Error +92 92 | +93 93 | def test_fail_if_equal(self): +94 |- self.failIfEqual(1, 2) # Error + 94 |+ assert 1 != 2 # Error diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap index 0715f78d5c547..ca94e0c21291a 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap @@ -1,47 +1,47 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:17:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -16 | def test_error_no_argument_given(): -17 | with pytest.raises(ValueError): +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): | ^^^^^^^^^^ PT011 -18 | raise ValueError("Can't divide 1 by 0") +19 | raise ValueError("Can't divide 1 by 0") | -PT011.py:20:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception | -18 | raise ValueError("Can't divide 1 by 0") -19 | -20 | with pytest.raises(socket.error): +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): | ^^^^^^^^^^^^ PT011 -21 | raise ValueError("Can't divide 1 by 0") +22 | raise ValueError("Can't divide 1 by 0") | -PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -24 | def test_error_match_is_empty(): -25 | with pytest.raises(ValueError, match=None): +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): | ^^^^^^^^^^ PT011 -26 | raise ValueError("Can't divide 1 by 0") +33 | raise ValueError("Can't divide 1 by 0") | -PT011.py:28:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -26 | raise ValueError("Can't divide 1 by 0") -27 | -28 | with pytest.raises(ValueError, match=""): +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): | ^^^^^^^^^^ PT011 -29 | raise ValueError("Can't divide 1 by 0") +36 | raise ValueError("Can't divide 1 by 0") | -PT011.py:31:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -29 | raise ValueError("Can't divide 1 by 0") -30 | -31 | with pytest.raises(ValueError, match=f""): +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): | ^^^^^^^^^^ PT011 -32 | raise ValueError("Can't divide 1 by 0") +39 | raise ValueError("Can't divide 1 by 0") | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap index f338e56158774..023618c278eed 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap @@ -1,55 +1,55 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:12:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception | -11 | def test_ok_different_error_from_config(): -12 | with pytest.raises(ZeroDivisionError): +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): | ^^^^^^^^^^^^^^^^^ PT011 -13 | raise ZeroDivisionError("Can't divide by 0") +14 | raise ZeroDivisionError("Can't divide by 0") | -PT011.py:17:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -16 | def test_error_no_argument_given(): -17 | with pytest.raises(ValueError): +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): | ^^^^^^^^^^ PT011 -18 | raise ValueError("Can't divide 1 by 0") +19 | raise ValueError("Can't divide 1 by 0") | -PT011.py:20:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception | -18 | raise ValueError("Can't divide 1 by 0") -19 | -20 | with pytest.raises(socket.error): +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): | ^^^^^^^^^^^^ PT011 -21 | raise ValueError("Can't divide 1 by 0") +22 | raise ValueError("Can't divide 1 by 0") | -PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -24 | def test_error_match_is_empty(): -25 | with pytest.raises(ValueError, match=None): +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): | ^^^^^^^^^^ PT011 -26 | raise ValueError("Can't divide 1 by 0") +33 | raise ValueError("Can't divide 1 by 0") | -PT011.py:28:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -26 | raise ValueError("Can't divide 1 by 0") -27 | -28 | with pytest.raises(ValueError, match=""): +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): | ^^^^^^^^^^ PT011 -29 | raise ValueError("Can't divide 1 by 0") +36 | raise ValueError("Can't divide 1 by 0") | -PT011.py:31:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -29 | raise ValueError("Can't divide 1 by 0") -30 | -31 | with pytest.raises(ValueError, match=f""): +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): | ^^^^^^^^^^ PT011 -32 | raise ValueError("Can't divide 1 by 0") +39 | raise ValueError("Can't divide 1 by 0") | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap new file mode 100644 index 0000000000000..f10518091d66c --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap @@ -0,0 +1,73 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception + | +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): + | ^^^^^^^^^^^^^^^^^ PT011 +14 | raise ZeroDivisionError("Can't divide by 0") + | + +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): + | ^^^^^^^^^^ PT011 +19 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception + | +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): + | ^^^^^^^^^^^^ PT011 +22 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +22 | raise ValueError("Can't divide 1 by 0") +23 | +24 | with pytest.raises(PicklingError): + | ^^^^^^^^^^^^^ PT011 +25 | raise PicklingError("Can't pickle") + | + +PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +25 | raise PicklingError("Can't pickle") +26 | +27 | with pytest.raises(UnpicklingError): + | ^^^^^^^^^^^^^^^ PT011 +28 | raise UnpicklingError("Can't unpickle") + | + +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): + | ^^^^^^^^^^ PT011 +33 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): + | ^^^^^^^^^^ PT011 +36 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): + | ^^^^^^^^^^ PT011 +39 | raise ValueError("Can't divide 1 by 0") + | + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap new file mode 100644 index 0000000000000..53d44920d6eb9 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +22 | raise ValueError("Can't divide 1 by 0") +23 | +24 | with pytest.raises(PicklingError): + | ^^^^^^^^^^^^^ PT011 +25 | raise PicklingError("Can't pickle") + | + +PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +25 | raise PicklingError("Can't pickle") +26 | +27 | with pytest.raises(UnpicklingError): + | ^^^^^^^^^^^^^^^ PT011 +28 | raise UnpicklingError("Can't unpickle") + | + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap index a533ba0f815c3..9e4a8533c965d 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap @@ -1,12 +1,12 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:12:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception | -11 | def test_ok_different_error_from_config(): -12 | with pytest.raises(ZeroDivisionError): +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): | ^^^^^^^^^^^^^^^^^ PT011 -13 | raise ZeroDivisionError("Can't divide by 0") +14 | raise ZeroDivisionError("Can't divide by 0") | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT014.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT014.snap new file mode 100644 index 0000000000000..091cc25bc48ad --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT014.snap @@ -0,0 +1,169 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT014.py:4:35: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +4 | @pytest.mark.parametrize("x", [1, 1, 2]) + | ^ PT014 +5 | def test_error_literal(x): +6 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +1 1 | import pytest +2 2 | +3 3 | +4 |-@pytest.mark.parametrize("x", [1, 1, 2]) + 4 |+@pytest.mark.parametrize("x", [1, 2]) +5 5 | def test_error_literal(x): +6 6 | ... +7 7 | + +PT014.py:14:35: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +14 | @pytest.mark.parametrize("x", [a, a, b, b, b, c]) + | ^ PT014 +15 | def test_error_expr_simple(x): +16 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +11 11 | c = 3 +12 12 | +13 13 | +14 |-@pytest.mark.parametrize("x", [a, a, b, b, b, c]) + 14 |+@pytest.mark.parametrize("x", [a, b, b, b, c]) +15 15 | def test_error_expr_simple(x): +16 16 | ... +17 17 | + +PT014.py:14:41: PT014 [*] Duplicate of test case at index 2 in `@pytest_mark.parametrize` + | +14 | @pytest.mark.parametrize("x", [a, a, b, b, b, c]) + | ^ PT014 +15 | def test_error_expr_simple(x): +16 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +11 11 | c = 3 +12 12 | +13 13 | +14 |-@pytest.mark.parametrize("x", [a, a, b, b, b, c]) + 14 |+@pytest.mark.parametrize("x", [a, a, b, b, c]) +15 15 | def test_error_expr_simple(x): +16 16 | ... +17 17 | + +PT014.py:14:44: PT014 [*] Duplicate of test case at index 2 in `@pytest_mark.parametrize` + | +14 | @pytest.mark.parametrize("x", [a, a, b, b, b, c]) + | ^ PT014 +15 | def test_error_expr_simple(x): +16 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +11 11 | c = 3 +12 12 | +13 13 | +14 |-@pytest.mark.parametrize("x", [a, a, b, b, b, c]) + 14 |+@pytest.mark.parametrize("x", [a, a, b, b, c]) +15 15 | def test_error_expr_simple(x): +16 16 | ... +17 17 | + +PT014.py:24:9: PT014 Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +22 | (a, b), +23 | # comment +24 | (a, b), + | ^^^^^^ PT014 +25 | (b, c), +26 | ], + | + = help: Remove duplicate test case + +PT014.py:32:39: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +32 | @pytest.mark.parametrize("x", [a, b, (a), c, ((a))]) + | ^ PT014 +33 | def test_error_parentheses(x): +34 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +29 29 | ... +30 30 | +31 31 | +32 |-@pytest.mark.parametrize("x", [a, b, (a), c, ((a))]) + 32 |+@pytest.mark.parametrize("x", [a, b, c, ((a))]) +33 33 | def test_error_parentheses(x): +34 34 | ... +35 35 | + +PT014.py:32:48: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +32 | @pytest.mark.parametrize("x", [a, b, (a), c, ((a))]) + | ^ PT014 +33 | def test_error_parentheses(x): +34 | ... + | + = help: Remove duplicate test case + +ℹ Suggested fix +29 29 | ... +30 30 | +31 31 | +32 |-@pytest.mark.parametrize("x", [a, b, (a), c, ((a))]) + 32 |+@pytest.mark.parametrize("x", [a, b, (a), c]) +33 33 | def test_error_parentheses(x): +34 34 | ... +35 35 | + +PT014.py:42:10: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +40 | a, +41 | b, +42 | (a), + | ^ PT014 +43 | c, +44 | ((a)), + | + = help: Remove duplicate test case + +ℹ Suggested fix +39 39 | [ +40 40 | a, +41 41 | b, +42 |- (a), +43 42 | c, +44 43 | ((a)), +45 44 | ], + +PT014.py:44:11: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +42 | (a), +43 | c, +44 | ((a)), + | ^ PT014 +45 | ], +46 | ) + | + = help: Remove duplicate test case + +ℹ Suggested fix +41 41 | b, +42 42 | (a), +43 43 | c, +44 |- ((a)), +45 44 | ], +46 45 | ) +47 46 | def test_error_parentheses_trailing_comma(x): + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap index cbfde1160d924..d9c9771a7d5d8 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap @@ -299,6 +299,8 @@ PT018.py:44:1: PT018 [*] Assertion should be broken down into multiple parts 44 |+assert something 45 |+assert something_else 45 46 | assert something and something_else and something_third # Error +46 47 | +47 48 | PT018.py:45:1: PT018 [*] Assertion should be broken down into multiple parts | @@ -316,5 +318,37 @@ PT018.py:45:1: PT018 [*] Assertion should be broken down into multiple parts 45 |-assert something and something_else and something_third # Error 45 |+assert something and something_else 46 |+assert something_third +46 47 | +47 48 | +48 49 | def test_multiline(): + +PT018.py:49:5: PT018 Assertion should be broken down into multiple parts + | +48 | def test_multiline(): +49 | assert something and something_else; x = 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PT018 +50 | +51 | x = 1; assert something and something_else + | + = help: Break down assertion into multiple parts + +PT018.py:51:12: PT018 Assertion should be broken down into multiple parts + | +49 | assert something and something_else; x = 1 +50 | +51 | x = 1; assert something and something_else + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PT018 +52 | +53 | x = 1; \ + | + = help: Break down assertion into multiple parts + +PT018.py:54:9: PT018 Assertion should be broken down into multiple parts + | +53 | x = 1; \ +54 | assert something and something_else + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PT018 + | + = help: Break down assertion into multiple parts diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_0.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_0.snap new file mode 100644 index 0000000000000..8ac1da881c437 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_0.snap @@ -0,0 +1,248 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT027_0.py:6:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaises` + | +4 | class Test(unittest.TestCase): +5 | def test_errors(self): +6 | with self.assertRaises(ValueError): + | ^^^^^^^^^^^^^^^^^ PT027 +7 | raise ValueError +8 | with self.assertRaises(expected_exception=ValueError): + | + = help: Replace `assertRaises` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +5 6 | def test_errors(self): +6 |- with self.assertRaises(ValueError): + 7 |+ with pytest.raises(ValueError): +7 8 | raise ValueError +8 9 | with self.assertRaises(expected_exception=ValueError): +9 10 | raise ValueError + +PT027_0.py:8:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaises` + | +6 | with self.assertRaises(ValueError): +7 | raise ValueError +8 | with self.assertRaises(expected_exception=ValueError): + | ^^^^^^^^^^^^^^^^^ PT027 +9 | raise ValueError + | + = help: Replace `assertRaises` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +5 6 | def test_errors(self): +6 7 | with self.assertRaises(ValueError): +7 8 | raise ValueError +8 |- with self.assertRaises(expected_exception=ValueError): + 9 |+ with pytest.raises(ValueError): +9 10 | raise ValueError +10 11 | +11 12 | with self.failUnlessRaises(ValueError): + +PT027_0.py:11:14: PT027 [*] Use `pytest.raises` instead of unittest-style `failUnlessRaises` + | + 9 | raise ValueError +10 | +11 | with self.failUnlessRaises(ValueError): + | ^^^^^^^^^^^^^^^^^^^^^ PT027 +12 | raise ValueError + | + = help: Replace `failUnlessRaises` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +8 9 | with self.assertRaises(expected_exception=ValueError): +9 10 | raise ValueError +10 11 | +11 |- with self.failUnlessRaises(ValueError): + 12 |+ with pytest.raises(ValueError): +12 13 | raise ValueError +13 14 | +14 15 | with self.assertRaisesRegex(ValueError, "test"): + +PT027_0.py:14:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaisesRegex` + | +12 | raise ValueError +13 | +14 | with self.assertRaisesRegex(ValueError, "test"): + | ^^^^^^^^^^^^^^^^^^^^^^ PT027 +15 | raise ValueError("test") + | + = help: Replace `assertRaisesRegex` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +11 12 | with self.failUnlessRaises(ValueError): +12 13 | raise ValueError +13 14 | +14 |- with self.assertRaisesRegex(ValueError, "test"): + 15 |+ with pytest.raises(ValueError, match="test"): +15 16 | raise ValueError("test") +16 17 | +17 18 | with self.assertRaisesRegex(ValueError, expected_regex="test"): + +PT027_0.py:17:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaisesRegex` + | +15 | raise ValueError("test") +16 | +17 | with self.assertRaisesRegex(ValueError, expected_regex="test"): + | ^^^^^^^^^^^^^^^^^^^^^^ PT027 +18 | raise ValueError("test") + | + = help: Replace `assertRaisesRegex` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +14 15 | with self.assertRaisesRegex(ValueError, "test"): +15 16 | raise ValueError("test") +16 17 | +17 |- with self.assertRaisesRegex(ValueError, expected_regex="test"): + 18 |+ with pytest.raises(ValueError, match="test"): +18 19 | raise ValueError("test") +19 20 | +20 21 | with self.assertRaisesRegex( + +PT027_0.py:20:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaisesRegex` + | +18 | raise ValueError("test") +19 | +20 | with self.assertRaisesRegex( + | ^^^^^^^^^^^^^^^^^^^^^^ PT027 +21 | expected_exception=ValueError, expected_regex="test" +22 | ): + | + = help: Replace `assertRaisesRegex` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +17 18 | with self.assertRaisesRegex(ValueError, expected_regex="test"): +18 19 | raise ValueError("test") +19 20 | +20 |- with self.assertRaisesRegex( +21 |- expected_exception=ValueError, expected_regex="test" +22 |- ): + 21 |+ with pytest.raises(ValueError, match="test"): +23 22 | raise ValueError("test") +24 23 | +25 24 | with self.assertRaisesRegex( + +PT027_0.py:25:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaisesRegex` + | +23 | raise ValueError("test") +24 | +25 | with self.assertRaisesRegex( + | ^^^^^^^^^^^^^^^^^^^^^^ PT027 +26 | expected_regex="test", expected_exception=ValueError +27 | ): + | + = help: Replace `assertRaisesRegex` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +22 23 | ): +23 24 | raise ValueError("test") +24 25 | +25 |- with self.assertRaisesRegex( +26 |- expected_regex="test", expected_exception=ValueError +27 |- ): + 26 |+ with pytest.raises(ValueError, match="test"): +28 27 | raise ValueError("test") +29 28 | +30 29 | with self.assertRaisesRegexp(ValueError, "test"): + +PT027_0.py:30:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaisesRegexp` + | +28 | raise ValueError("test") +29 | +30 | with self.assertRaisesRegexp(ValueError, "test"): + | ^^^^^^^^^^^^^^^^^^^^^^^ PT027 +31 | raise ValueError("test") + | + = help: Replace `assertRaisesRegexp` with `pytest.raises` + +ℹ Suggested fix +1 1 | import unittest + 2 |+import pytest +2 3 | +3 4 | +4 5 | class Test(unittest.TestCase): +-------------------------------------------------------------------------------- +27 28 | ): +28 29 | raise ValueError("test") +29 30 | +30 |- with self.assertRaisesRegexp(ValueError, "test"): + 31 |+ with pytest.raises(ValueError, match="test"): +31 32 | raise ValueError("test") +32 33 | +33 34 | def test_unfixable_errors(self): + +PT027_0.py:34:14: PT027 Use `pytest.raises` instead of unittest-style `assertRaises` + | +33 | def test_unfixable_errors(self): +34 | with self.assertRaises(ValueError, msg="msg"): + | ^^^^^^^^^^^^^^^^^ PT027 +35 | raise ValueError + | + = help: Replace `assertRaises` with `pytest.raises` + +PT027_0.py:37:14: PT027 Use `pytest.raises` instead of unittest-style `assertRaises` + | +35 | raise ValueError +36 | +37 | with self.assertRaises( + | ^^^^^^^^^^^^^^^^^ PT027 +38 | # comment +39 | ValueError + | + = help: Replace `assertRaises` with `pytest.raises` + +PT027_0.py:44:13: PT027 Use `pytest.raises` instead of unittest-style `assertRaises` + | +43 | with ( +44 | self + | _____________^ +45 | | # comment +46 | | .assertRaises(ValueError) + | |_________________________^ PT027 +47 | ): +48 | raise ValueError + | + = help: Replace `assertRaises` with `pytest.raises` + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_1.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_1.snap new file mode 100644 index 0000000000000..7656398481c0d --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT027_1.snap @@ -0,0 +1,21 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT027_1.py:11:14: PT027 [*] Use `pytest.raises` instead of unittest-style `assertRaises` + | +10 | def test_errors(self): +11 | with self.assertRaises(ValueError): + | ^^^^^^^^^^^^^^^^^ PT027 +12 | raise ValueError + | + = help: Replace `assertRaises` with `pytest.raises` + +ℹ Suggested fix +8 8 | raise ValueError +9 9 | +10 10 | def test_errors(self): +11 |- with self.assertRaises(ValueError): + 11 |+ with pytest.raises(ValueError): +12 12 | raise ValueError + + diff --git a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs index 9fc73384350aa..bd54d74304616 100644 --- a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs +++ b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs @@ -1,10 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Ranged}; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::{TextRange, TextSize}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_source_file::Locator; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -47,65 +43,39 @@ impl AlwaysAutofixableViolation for UnnecessaryParenOnRaiseException { /// RSE102 pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: &Expr) { - if let Expr::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments, range: _, }) = expr - { - if args.is_empty() && keywords.is_empty() { - // `raise func()` still requires parentheses; only `raise Class()` does not. - if checker - .semantic() - .lookup_attribute(func) - .map_or(false, |id| { - checker.semantic().binding(id).kind.is_function_definition() - }) - { - return; - } + else { + return; + }; - let range = match_parens(func.end(), checker.locator()) - .expect("Expected call to include parentheses"); - let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::deletion(func.end(), range.end()))); - } - checker.diagnostics.push(diagnostic); + if arguments.is_empty() { + // `raise func()` still requires parentheses; only `raise Class()` does not. + if checker + .semantic() + .lookup_attribute(func) + .is_some_and(|id| checker.semantic().binding(id).kind.is_function_definition()) + { + return; } - } -} -/// Return the range of the first parenthesis pair after a given [`TextSize`]. -fn match_parens(start: TextSize, locator: &Locator) -> Option { - let contents = &locator.contents()[usize::from(start)..]; - - let mut fix_start = None; - let mut fix_end = None; - let mut count = 0u32; - - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, start).flatten() { - match tok { - Tok::Lpar => { - if count == 0 { - fix_start = Some(range.start()); - } - count = count.saturating_add(1); - } - Tok::Rpar => { - count = count.saturating_sub(1); - if count == 0 { - fix_end = Some(range.end()); - break; - } - } - _ => {} + // `ctypes.WinError()` is a function, not a class. It's part of the standard library, so + // we might as well get it right. + if checker + .semantic() + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["ctypes", "WinError"])) + { + return; } - } - match (fix_start, fix_end) { - (Some(start), Some(end)) => Some(TextRange::new(start, end)), - _ => None, + let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.set_fix(Fix::automatic(Edit::range_deletion(arguments.range()))); + } + checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap b/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap index 4f905dd654c0a..61b7f00a95503 100644 --- a/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap +++ b/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap @@ -57,7 +57,7 @@ RSE102.py:16:17: RSE102 [*] Unnecessary parentheses on raised exception 14 14 | 15 15 | # RSE102 16 |-raise TypeError () - 16 |+raise TypeError + 16 |+raise TypeError 17 17 | 18 18 | # RSE102 19 19 | raise TypeError \ @@ -74,64 +74,109 @@ RSE102.py:20:5: RSE102 [*] Unnecessary parentheses on raised exception = help: Remove unnecessary parentheses ℹ Fix -16 16 | raise TypeError () 17 17 | 18 18 | # RSE102 -19 |-raise TypeError \ +19 19 | raise TypeError \ 20 |- () - 19 |+raise TypeError -21 20 | -22 21 | # RSE102 -23 22 | raise TypeError( + 20 |+ +21 21 | +22 22 | # RSE102 +23 23 | raise TypeError \ -RSE102.py:23:16: RSE102 [*] Unnecessary parentheses on raised exception +RSE102.py:24:5: RSE102 [*] Unnecessary parentheses on raised exception | -22 | # RSE102 -23 | raise TypeError( - | ________________^ -24 | | -25 | | ) - | |_^ RSE102 -26 | -27 | # RSE102 +22 | # RSE102 +23 | raise TypeError \ +24 | (); + | ^^ RSE102 +25 | +26 | # RSE102 | = help: Remove unnecessary parentheses ℹ Fix -20 20 | () 21 21 | 22 22 | # RSE102 -23 |-raise TypeError( -24 |- -25 |-) - 23 |+raise TypeError -26 24 | -27 25 | # RSE102 -28 26 | raise TypeError( - -RSE102.py:28:16: RSE102 [*] Unnecessary parentheses on raised exception +23 23 | raise TypeError \ +24 |- (); + 24 |+ ; +25 25 | +26 26 | # RSE102 +27 27 | raise TypeError( + +RSE102.py:27:16: RSE102 [*] Unnecessary parentheses on raised exception + | +26 | # RSE102 +27 | raise TypeError( + | ________________^ +28 | | +29 | | ) + | |_^ RSE102 +30 | +31 | # RSE102 + | + = help: Remove unnecessary parentheses + +ℹ Fix +24 24 | (); +25 25 | +26 26 | # RSE102 +27 |-raise TypeError( +28 |- +29 |-) + 27 |+raise TypeError +30 28 | +31 29 | # RSE102 +32 30 | raise (TypeError) ( + +RSE102.py:32:19: RSE102 [*] Unnecessary parentheses on raised exception + | +31 | # RSE102 +32 | raise (TypeError) ( + | ___________________^ +33 | | +34 | | ) + | |_^ RSE102 +35 | +36 | # RSE102 + | + = help: Remove unnecessary parentheses + +ℹ Fix +29 29 | ) +30 30 | +31 31 | # RSE102 +32 |-raise (TypeError) ( +33 |- +34 |-) + 32 |+raise (TypeError) +35 33 | +36 34 | # RSE102 +37 35 | raise TypeError( + +RSE102.py:37:16: RSE102 [*] Unnecessary parentheses on raised exception | -27 | # RSE102 -28 | raise TypeError( +36 | # RSE102 +37 | raise TypeError( | ________________^ -29 | | # Hello, world! -30 | | ) +38 | | # Hello, world! +39 | | ) | |_^ RSE102 -31 | -32 | # OK +40 | +41 | # OK | = help: Remove unnecessary parentheses ℹ Fix -25 25 | ) -26 26 | -27 27 | # RSE102 -28 |-raise TypeError( -29 |- # Hello, world! -30 |-) - 28 |+raise TypeError -31 29 | -32 30 | # OK -33 31 | raise AssertionError +34 34 | ) +35 35 | +36 36 | # RSE102 +37 |-raise TypeError( +38 |- # Hello, world! +39 |-) + 37 |+raise TypeError +40 38 | +41 39 | # OK +42 40 | raise AssertionError diff --git a/crates/ruff/src/rules/flake8_return/helpers.rs b/crates/ruff/src/rules/flake8_return/helpers.rs index 668e283b1d22e..a24cae600ff23 100644 --- a/crates/ruff/src/rules/flake8_return/helpers.rs +++ b/crates/ruff/src/rules/flake8_return/helpers.rs @@ -8,7 +8,7 @@ use ruff_source_file::{Locator, UniversalNewlines}; /// non-`None` value. pub(super) fn result_exists(returns: &[&ast::StmtReturn]) -> bool { returns.iter().any(|stmt| { - stmt.value.as_deref().map_or(false, |value| { + stmt.value.as_deref().is_some_and(|value| { !matches!( value, Expr::Constant(constant) if constant.value.is_none() @@ -25,19 +25,11 @@ pub(super) fn result_exists(returns: &[&ast::StmtReturn]) -> bool { /// This method assumes that the statement is the last statement in its body; specifically, that /// the statement isn't followed by a semicolon, followed by a multi-line statement. pub(super) fn end_of_last_statement(stmt: &Stmt, locator: &Locator) -> TextSize { - if stmt.end() == locator.text_len() { - // End-of-file, so just return the end of the statement. - stmt.end() - } else { - // Otherwise, find the end of the last line that's "part of" the statement. - let contents = locator.after(stmt.end()); - - for line in contents.universal_newlines() { - if !line.ends_with('\\') { - return stmt.end() + line.end(); - } + // Find the end of the last line that's "part of" the statement. + for line in locator.after(stmt.end()).universal_newlines() { + if !line.ends_with('\\') { + return stmt.end() + line.end(); } - - unreachable!("Expected to find end-of-statement") } + locator.text_len() } diff --git a/crates/ruff/src/rules/flake8_return/rules/function.rs b/crates/ruff/src/rules/flake8_return/rules/function.rs index 6812891de0aef..5d604c6e4a60e 100644 --- a/crates/ruff/src/rules/flake8_return/rules/function.rs +++ b/crates/ruff/src/rules/flake8_return/rules/function.rs @@ -373,7 +373,7 @@ fn implicit_return_value(checker: &mut Checker, stack: &Stack) { /// Return `true` if the `func` is a known function that never returns. fn is_noreturn_func(func: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(func).map_or(false, |call_path| { + semantic.resolve_call_path(func).is_some_and(|call_path| { matches!( call_path.as_slice(), ["" | "builtins" | "sys" | "_thread" | "pytest", "exit"] @@ -425,9 +425,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { } Stmt::Assert(ast::StmtAssert { test, .. }) if is_const_false(test) => {} Stmt::While(ast::StmtWhile { test, .. }) if is_const_true(test) => {} - Stmt::For(ast::StmtFor { orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | Stmt::While(ast::StmtWhile { orelse, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) | Stmt::While(ast::StmtWhile { orelse, .. }) => { if let Some(last_stmt) = orelse.last() { implicit_return(checker, last_stmt); } else { @@ -454,13 +452,12 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { } } } - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) => { if let Some(last_stmt) = body.last() { implicit_return(checker, last_stmt); } } - Stmt::Return(_) | Stmt::Raise(_) | Stmt::Try(_) | Stmt::TryStar(_) => {} + Stmt::Return(_) | Stmt::Raise(_) | Stmt::Try(_) => {} Stmt::Expr(ast::StmtExpr { value, .. }) if matches!( value.as_ref(), @@ -552,7 +549,7 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) { if content[after_equals..] .chars() .next() - .map_or(false, char::is_alphabetic) + .is_some_and(char::is_alphabetic) { "return ".to_string() } else { @@ -561,7 +558,7 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) { // Replace from the start of the assignment statement to the end of the equals // sign. TextRange::new( - assign.range().start(), + assign.start(), assign .range() .start() diff --git a/crates/ruff/src/rules/flake8_return/snapshots/ruff__rules__flake8_return__tests__RET503_RET503.py.snap b/crates/ruff/src/rules/flake8_return/snapshots/ruff__rules__flake8_return__tests__RET503_RET503.py.snap index 8c8fd2cb46eb0..9627ff3dca666 100644 --- a/crates/ruff/src/rules/flake8_return/snapshots/ruff__rules__flake8_return__tests__RET503_RET503.py.snap +++ b/crates/ruff/src/rules/flake8_return/snapshots/ruff__rules__flake8_return__tests__RET503_RET503.py.snap @@ -380,5 +380,24 @@ RET503.py:320:9: RET503 [*] Missing explicit `return` at the end of function abl 321 321 | return "" \ 322 322 | ; # type: ignore 323 |+ return None +323 324 | +324 325 | +325 326 | def end_of_file(): + +RET503.py:328:5: RET503 [*] Missing explicit `return` at the end of function able to return non-`None` value + | +326 | if False: +327 | return 1 +328 | x = 2 \ + | ^^^^^ RET503 + | + = help: Add explicit `return` statement + +ℹ Suggested fix +326 326 | if False: +327 327 | return 1 +328 328 | x = 2 \ + 329 |+ + 330 |+ return None diff --git a/crates/ruff/src/rules/flake8_return/visitor.rs b/crates/ruff/src/rules/flake8_return/visitor.rs index c5ffe1585caae..775c3356e5f72 100644 --- a/crates/ruff/src/rules/flake8_return/visitor.rs +++ b/crates/ruff/src/rules/flake8_return/visitor.rs @@ -46,13 +46,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { return; } Stmt::FunctionDef(ast::StmtFunctionDef { - args, - decorator_list, - returns, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - args, + parameters, decorator_list, returns, .. @@ -66,7 +60,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { if let Some(returns) = returns { visitor::walk_expr(self, returns); } - visitor::walk_arguments(self, args); + visitor::walk_parameters(self, parameters); self.parents.pop(); // But don't recurse into the body. @@ -101,8 +95,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> { // x = f.read() // return x // ``` - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) => { if let Some(stmt_assign) = body.last().and_then(Stmt::as_assign_stmt) { self.stack .assignment_return diff --git a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs index 8abb5efb00dad..8749d54b524dc 100644 --- a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs +++ b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs @@ -1,9 +1,8 @@ -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::collect_call_path; -use ruff_python_semantic::ScopeKind; +use ruff_python_ast::{self as ast, Expr, Ranged}; +use ruff_python_semantic::{BindingKind, ScopeKind}; use crate::checkers::ast::Checker; @@ -62,125 +61,132 @@ impl Violation for PrivateMemberAccess { /// SLF001 pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) { - if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = expr { - if (attr.starts_with("__") && !attr.ends_with("__")) - || (attr.starts_with('_') && !attr.starts_with("__")) + let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = expr else { + return; + }; + + if (attr.starts_with("__") && !attr.ends_with("__")) + || (attr.starts_with('_') && !attr.starts_with("__")) + { + if checker + .settings + .flake8_self + .ignore_names + .contains(attr.as_ref()) { - if checker - .settings - .flake8_self - .ignore_names - .contains(attr.as_ref()) - { + return; + } + + // Ignore accesses on instances within special methods (e.g., `__eq__`). + if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) = + checker.semantic().current_scope().kind + { + if matches!( + name.as_str(), + "__lt__" + | "__le__" + | "__eq__" + | "__ne__" + | "__gt__" + | "__ge__" + | "__add__" + | "__sub__" + | "__mul__" + | "__matmul__" + | "__truediv__" + | "__floordiv__" + | "__mod__" + | "__divmod__" + | "__pow__" + | "__lshift__" + | "__rshift__" + | "__and__" + | "__xor__" + | "__or__" + | "__radd__" + | "__rsub__" + | "__rmul__" + | "__rmatmul__" + | "__rtruediv__" + | "__rfloordiv__" + | "__rmod__" + | "__rdivmod__" + | "__rpow__" + | "__rlshift__" + | "__rrshift__" + | "__rand__" + | "__rxor__" + | "__ror__" + | "__iadd__" + | "__isub__" + | "__imul__" + | "__imatmul__" + | "__itruediv__" + | "__ifloordiv__" + | "__imod__" + | "__ipow__" + | "__ilshift__" + | "__irshift__" + | "__iand__" + | "__ixor__" + | "__ior__" + ) { return; } + } - // Ignore accesses on instances within special methods (e.g., `__eq__`). - if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) = - checker.semantic().scope().kind - { - if matches!( - name.as_str(), - "__lt__" - | "__le__" - | "__eq__" - | "__ne__" - | "__gt__" - | "__ge__" - | "__add__" - | "__sub__" - | "__mul__" - | "__matmul__" - | "__truediv__" - | "__floordiv__" - | "__mod__" - | "__divmod__" - | "__pow__" - | "__lshift__" - | "__rshift__" - | "__and__" - | "__xor__" - | "__or__" - | "__radd__" - | "__rsub__" - | "__rmul__" - | "__rmatmul__" - | "__rtruediv__" - | "__rfloordiv__" - | "__rmod__" - | "__rdivmod__" - | "__rpow__" - | "__rlshift__" - | "__rrshift__" - | "__rand__" - | "__rxor__" - | "__ror__" - | "__iadd__" - | "__isub__" - | "__imul__" - | "__imatmul__" - | "__itruediv__" - | "__ifloordiv__" - | "__imod__" - | "__ipow__" - | "__ilshift__" - | "__irshift__" - | "__iand__" - | "__ixor__" - | "__ior__" - ) { - return; - } + // Allow some documented private methods, like `os._exit()`. + if let Some(call_path) = checker.semantic().resolve_call_path(expr) { + if matches!(call_path.as_slice(), ["os", "_exit"]) { + return; } + } - if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { - // Ignore `super()` calls. - if let Some(call_path) = collect_call_path(func) { - if matches!(call_path.as_slice(), ["super"]) { - return; - } - } - } else if let Some(call_path) = collect_call_path(value) { - // Ignore `self` and `cls` accesses. - if matches!(call_path.as_slice(), ["self" | "cls" | "mcs"]) { + if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { + // Ignore `super()` calls. + if let Some(call_path) = collect_call_path(func) { + if matches!(call_path.as_slice(), ["super"]) { return; } + } + } - // Ignore accesses on class members from _within_ the class. - if checker - .semantic() - .scopes - .iter() - .rev() - .find_map(|scope| match &scope.kind { - ScopeKind::Class(ast::StmtClassDef { name, .. }) => Some(name), - _ => None, - }) - .map_or(false, |name| { - if call_path.as_slice() == [name.as_str()] { - checker - .semantic() - .find_binding(name) - .map_or(false, |binding| { - // TODO(charlie): Could the name ever be bound to a - // _different_ class here? - binding.kind.is_class_definition() - }) - } else { - false - } - }) - { - return; - } + if let Some(call_path) = collect_call_path(value) { + // Ignore `self` and `cls` accesses. + if matches!(call_path.as_slice(), ["self" | "cls" | "mcs"]) { + return; } + } - checker.diagnostics.push(Diagnostic::new( - PrivateMemberAccess { - access: attr.to_string(), - }, - expr.range(), - )); + if let Expr::Name(name) = value.as_ref() { + // Ignore accesses on class members from _within_ the class. + if checker + .semantic() + .resolve_name(name) + .and_then(|id| { + if let BindingKind::ClassDefinition(scope) = checker.semantic().binding(id).kind + { + Some(scope) + } else { + None + } + }) + .is_some_and(|scope| { + checker + .semantic() + .current_scope_ids() + .any(|parent| scope == parent) + }) + { + return; + } } + + checker.diagnostics.push(Diagnostic::new( + PrivateMemberAccess { + access: attr.to_string(), + }, + expr.range(), + )); } } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs index c0bddafd13c85..d744ccdcb1dae 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs @@ -3,7 +3,7 @@ use std::iter; use itertools::Either::{Left, Right}; use itertools::Itertools; -use ruff_python_ast::{self as ast, BoolOp, CmpOp, Expr, ExprContext, Ranged, UnaryOp}; +use ruff_python_ast::{self as ast, Arguments, BoolOp, CmpOp, Expr, ExprContext, Ranged, UnaryOp}; use ruff_text_size::TextRange; use rustc_hash::FxHashMap; @@ -152,7 +152,7 @@ impl AlwaysAutofixableViolation for ExprAndNotExpr { /// /// ## Example /// ```python -/// x and not x +/// x or not x /// ``` /// /// ## References @@ -315,8 +315,12 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { // Verify that this is an `isinstance` call. let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) = &call else { @@ -351,7 +355,11 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { if indices.len() > 1 { // Grab the target used in each duplicate `isinstance` call (e.g., `obj` in // `isinstance(obj, int)`). - let target = if let Expr::Call(ast::ExprCall { args, .. }) = &values[indices[0]] { + let target = if let Expr::Call(ast::ExprCall { + arguments: Arguments { args, .. }, + .. + }) = &values[indices[0]] + { args.get(0).expect("`isinstance` should have two arguments") } else { unreachable!("Indices should only contain `isinstance` calls") @@ -374,7 +382,11 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { .iter() .map(|index| &values[*index]) .map(|expr| { - let Expr::Call(ast::ExprCall { args, .. }) = expr else { + let Expr::Call(ast::ExprCall { + arguments: Arguments { args, .. }, + .. + }) = expr + else { unreachable!("Indices should only contain `isinstance` calls") }; args.get(1).expect("`isinstance` should have two arguments") @@ -405,8 +417,11 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { }; let node2 = ast::ExprCall { func: Box::new(node1.into()), - args: vec![target.clone(), node.into()], - keywords: vec![], + arguments: Arguments { + args: vec![target.clone(), node.into()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let call = node2.into(); @@ -450,16 +465,15 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> { else { return None; }; - if ops.len() != 1 || comparators.len() != 1 { - return None; - } - if !matches!(&ops[0], CmpOp::Eq) { + if ops != &[CmpOp::Eq] { return None; } let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { return None; }; - let comparator = &comparators[0]; + let [comparator] = comparators.as_slice() else { + return None; + }; if !matches!(&comparator, Expr::Name(_)) { return None; } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs index ca1271a2a0b03..380a71bf0d270 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Ranged}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -103,14 +103,19 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex } // Ex) `os.environ.get('foo')`, `os.getenv('foo')` - let Expr::Call(ast::ExprCall { func, args, .. }) = expr else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) = expr + else { return; }; let Some(arg) = args.get(0) else { return; }; let Expr::Constant(ast::ExprConstant { - value: Constant::Str(env_var), + value: Constant::Str(ast::StringConstant { value: env_var, .. }), .. }) = arg else { @@ -119,7 +124,7 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["os", "environ", "get"] | ["os", "getenv"] @@ -162,7 +167,7 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { return; } let Expr::Constant(ast::ExprConstant { - value: Constant::Str(env_var), + value: Constant::Str(ast::StringConstant { value: env_var, .. }), kind, range: _, }) = slice.as_ref() @@ -200,8 +205,7 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: Arguments { args, keywords, .. }, range: _, }) = expr else { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs index e2c390059a32d..27d1b551421c8 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs @@ -1,7 +1,7 @@ use log::error; use ruff_python_ast::{ - self as ast, CmpOp, Constant, ElifElseClause, Expr, ExprContext, Identifier, Ranged, Stmt, - StmtIf, + self as ast, Arguments, CmpOp, Constant, ElifElseClause, Expr, ExprContext, Identifier, Ranged, + Stmt, }; use ruff_text_size::TextRange; use rustc_hash::FxHashSet; @@ -11,8 +11,8 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::{ComparableConstant, ComparableExpr, ComparableStmt}; use ruff_python_ast::helpers::{any_over_expr, contains_effect}; use ruff_python_ast::stmt_if::{if_elif_branches, IfElifBranch}; -use ruff_python_parser::first_colon_range; use ruff_python_semantic::SemanticModel; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_source_file::{Locator, UniversalNewlines}; use crate::checkers::ast::Checker; @@ -264,15 +264,13 @@ fn is_main_check(expr: &Expr) -> bool { { if let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() { if id == "__name__" { - if comparators.len() == 1 { - if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), - .. - }) = &comparators[0] - { - if value == "__main__" { - return true; - } + if let [Expr::Constant(ast::ExprConstant { + value: Constant::Str(ast::StringConstant { value, .. }), + .. + })] = comparators.as_slice() + { + if value == "__main__" { + return true; } } } @@ -314,8 +312,8 @@ fn find_last_nested_if(body: &[Stmt]) -> Option<(&Expr, &Stmt)> { } /// Returns the body, the range of the `if` or `elif` and whether the range is for an `if` or `elif` -fn nested_if_body(stmt_if: &StmtIf) -> Option<(&[Stmt], TextRange, bool)> { - let StmtIf { +fn nested_if_body(stmt_if: &ast::StmtIf) -> Option<(&[Stmt], TextRange, bool)> { + let ast::StmtIf { test, body, elif_else_clauses, @@ -361,21 +359,20 @@ fn nested_if_body(stmt_if: &StmtIf) -> Option<(&[Stmt], TextRange, bool)> { } /// SIM102 -pub(crate) fn nested_if_statements(checker: &mut Checker, stmt_if: &StmtIf, parent: Option<&Stmt>) { +pub(crate) fn nested_if_statements( + checker: &mut Checker, + stmt_if: &ast::StmtIf, + parent: Option<&Stmt>, +) { let Some((body, range, is_elif)) = nested_if_body(stmt_if) else { return; }; // Find the deepest nested if-statement, to inform the range. - let Some((test, first_stmt)) = find_last_nested_if(body) else { + let Some((test, _first_stmt)) = find_last_nested_if(body) else { return; }; - let colon = first_colon_range( - TextRange::new(test.end(), first_stmt.start()), - checker.locator().contents(), - ); - // Check if the parent is already emitting a larger diagnostic including this if statement if let Some(Stmt::If(stmt_if)) = parent { if let Some((body, _range, _is_elif)) = nested_if_body(stmt_if) { @@ -389,10 +386,14 @@ pub(crate) fn nested_if_statements(checker: &mut Checker, stmt_if: &StmtIf, pare } } - let mut diagnostic = Diagnostic::new( - CollapsibleIf, - colon.map_or(range, |colon| TextRange::new(range.start(), colon.end())), - ); + let Some(colon) = SimpleTokenizer::starts_at(test.end(), checker.locator().contents()) + .skip_trivia() + .find(|token| token.kind == SimpleTokenKind::Colon) + else { + return; + }; + + let mut diagnostic = Diagnostic::new(CollapsibleIf, TextRange::new(range.start(), colon.end())); if checker.patch(diagnostic.kind.rule()) { // The fixer preserves comments in the nested body, but removes comments between // the outer and inner if statements. @@ -538,8 +539,11 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { }; let node1 = ast::ExprCall { func: Box::new(node.into()), - args: vec![if_test.clone()], - keywords: vec![], + arguments: Arguments { + args: vec![if_test.clone()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let node2 = ast::StmtReturn { @@ -574,9 +578,9 @@ fn ternary(target_var: &Expr, body_value: &Expr, test: &Expr, orelse_value: &Exp /// Return `true` if the `Expr` contains a reference to any of the given `${module}.${target}`. fn contains_call_path(expr: &Expr, targets: &[&[&str]], semantic: &SemanticModel) -> bool { any_over_expr(expr, &|expr| { - semantic.resolve_call_path(expr).map_or(false, |call_path| { - targets.iter().any(|target| &call_path.as_slice() == target) - }) + semantic + .resolve_call_path(expr) + .is_some_and(|call_path| targets.iter().any(|target| &call_path.as_slice() == target)) }) } @@ -687,12 +691,12 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt) { fn body_range(branch: &IfElifBranch, locator: &Locator) -> TextRange { TextRange::new( locator.line_end(branch.test.end()), - locator.line_end(branch.range.end()), + locator.line_end(branch.end()), ) } /// SIM114 -pub(crate) fn if_with_same_arms(checker: &mut Checker, locator: &Locator, stmt_if: &StmtIf) { +pub(crate) fn if_with_same_arms(checker: &mut Checker, locator: &Locator, stmt_if: &ast::StmtIf) { let mut branches_iter = if_elif_branches(stmt_if).peekable(); while let Some(current_branch) = branches_iter.next() { let Some(following_branch) = branches_iter.peek() else { @@ -715,28 +719,34 @@ pub(crate) fn if_with_same_arms(checker: &mut Checker, locator: &Locator, stmt_i // ...and the same comments let first_comments = checker .indexer() - .comments_in_range(body_range(¤t_branch, locator), locator); + .comment_ranges() + .comments_in_range(body_range(¤t_branch, locator)) + .iter() + .map(|range| locator.slice(*range)); let second_comments = checker .indexer() - .comments_in_range(body_range(following_branch, locator), locator); + .comment_ranges() + .comments_in_range(body_range(following_branch, locator)) + .iter() + .map(|range| locator.slice(*range)); if !first_comments.eq(second_comments) { continue; } checker.diagnostics.push(Diagnostic::new( IfWithSameArms, - TextRange::new(current_branch.range.start(), following_branch.range.end()), + TextRange::new(current_branch.start(), following_branch.end()), )); } } /// SIM116 -pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &StmtIf) { +pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &ast::StmtIf) { // Throughout this rule: // * Each if or elif statement's test must consist of a constant equality check with the same variable. // * Each if or elif statement's body must consist of a single `return`. // * The else clause must be empty, or a single `return`. - let StmtIf { + let ast::StmtIf { body, test, elif_else_clauses, @@ -767,9 +777,10 @@ pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &StmtIf) { let [Stmt::Return(ast::StmtReturn { value, range: _ })] = body.as_slice() else { return; }; - if value.as_ref().map_or(false, |value| { - contains_effect(value, |id| checker.semantic().is_builtin(id)) - }) { + if value + .as_ref() + .is_some_and(|value| contains_effect(value, |id| checker.semantic().is_builtin(id))) + { return; } @@ -789,7 +800,7 @@ pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &StmtIf) { let [Stmt::Return(ast::StmtReturn { value, range: _ })] = body.as_slice() else { return; }; - if value.as_ref().map_or(false, |value| { + if value.as_ref().is_some_and(|value| { contains_effect(value, |id| checker.semantic().is_builtin(id)) }) { return; @@ -815,7 +826,7 @@ pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &StmtIf) { return; }; - if value.as_ref().map_or(false, |value| { + if value.as_ref().is_some_and(|value| { contains_effect(value, |id| checker.semantic().is_builtin(id)) }) { return; @@ -841,8 +852,8 @@ pub(crate) fn manual_dict_lookup(checker: &mut Checker, stmt_if: &StmtIf) { } /// SIM401 -pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &StmtIf) { - let StmtIf { +pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &ast::StmtIf) { + let ast::StmtIf { test, body, elif_else_clauses, @@ -871,7 +882,7 @@ pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &StmtIf) else { return; }; - if body_var.len() != 1 { + let [body_var] = body_var.as_slice() else { return; }; let Stmt::Assign(ast::StmtAssign { @@ -882,7 +893,7 @@ pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &StmtIf) else { return; }; - if orelse_var.len() != 1 { + let [orelse_var] = orelse_var.as_slice() else { return; }; let Expr::Compare(ast::ExprCompare { @@ -894,27 +905,16 @@ pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &StmtIf) else { return; }; - if test_dict.len() != 1 { + let [test_dict] = test_dict.as_slice() else { return; - } + }; let (expected_var, expected_value, default_var, default_value) = match ops[..] { - [CmpOp::In] => ( - &body_var[0], - body_value, - &orelse_var[0], - orelse_value.as_ref(), - ), - [CmpOp::NotIn] => ( - &orelse_var[0], - orelse_value, - &body_var[0], - body_value.as_ref(), - ), + [CmpOp::In] => (body_var, body_value, orelse_var, orelse_value.as_ref()), + [CmpOp::NotIn] => (orelse_var, orelse_value, body_var, body_value.as_ref()), _ => { return; } }; - let test_dict = &test_dict[0]; let Expr::Subscript(ast::ExprSubscript { value: expected_subscript, slice: expected_slice, @@ -948,8 +948,11 @@ pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &StmtIf) }; let node3 = ast::ExprCall { func: Box::new(node2.into()), - args: vec![node1, node], - keywords: vec![], + arguments: Arguments { + args: vec![node1, node], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let node4 = expected_var.clone(); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs index 21623a2392811..921ac370ee2eb 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, ExprContext, Ranged, UnaryOp}; +use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Ranged, UnaryOp}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -166,8 +166,11 @@ pub(crate) fn explicit_true_false_in_ifexpr( }; let node1 = ast::ExprCall { func: Box::new(node.into()), - args: vec![test.clone()], - keywords: vec![], + arguments: Arguments { + args: vec![test.clone()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs index 190673f5a9d60..f5da2c443bddf 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, CmpOp, Expr, ExprContext, Ranged, Stmt, UnaryOp}; +use ruff_python_ast::{self as ast, Arguments, CmpOp, Expr, ExprContext, Ranged, Stmt, UnaryOp}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -155,14 +155,13 @@ pub(crate) fn negation_with_equal_op( if !matches!(&ops[..], [CmpOp::Eq]) { return; } - if is_exception_check(checker.semantic().stmt()) { + if is_exception_check(checker.semantic().current_statement()) { return; } // Avoid flagging issues in dunder implementations. - if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) - | ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef { name, .. }) = - &checker.semantic().scope().kind + if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) = + &checker.semantic().current_scope().kind { if is_dunder_method(name) { return; @@ -213,14 +212,13 @@ pub(crate) fn negation_with_not_equal_op( if !matches!(&ops[..], [CmpOp::NotEq]) { return; } - if is_exception_check(checker.semantic().stmt()) { + if is_exception_check(checker.semantic().current_statement()) { return; } // Avoid flagging issues in dunder implementations. - if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) - | ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef { name, .. }) = - &checker.semantic().scope().kind + if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) = + &checker.semantic().current_scope().kind { if is_dunder_method(name) { return; @@ -286,8 +284,11 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o }; let node1 = ast::ExprCall { func: Box::new(node.into()), - args: vec![*operand.clone()], - keywords: vec![], + arguments: Arguments { + args: vec![*operand.clone()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs index 2a9ff71350d8c..95fe3d66bebef 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs @@ -1,12 +1,12 @@ use log::error; -use ruff_python_ast::{self as ast, Ranged, Stmt, WithItem}; -use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Violation}; use ruff_diagnostics::{Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_parser::first_colon_range; +use ruff_python_ast::{self as ast, Ranged, Stmt, WithItem}; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_source_file::UniversalNewlines; +use ruff_text_size::TextRange; use crate::checkers::ast::Checker; use crate::line_width::LineWidth; @@ -63,18 +63,22 @@ impl Violation for MultipleWithStatements { /// Returns a boolean indicating whether it's an async with statement, the items /// and body. fn next_with(body: &[Stmt]) -> Option<(bool, &[WithItem], &[Stmt])> { - match body { - [Stmt::With(ast::StmtWith { items, body, .. })] => Some((false, items, body)), - [Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. })] => Some((true, items, body)), - _ => None, - } + let [Stmt::With(ast::StmtWith { + is_async, + items, + body, + .. + })] = body + else { + return None; + }; + Some((*is_async, items, body)) } /// SIM117 pub(crate) fn multiple_with_statements( checker: &mut Checker, - with_stmt: &Stmt, - with_body: &[Stmt], + with_stmt: &ast::StmtWith, with_parent: Option<&Stmt>, ) { // Make sure we fix from top to bottom for nested with statements, e.g. for @@ -102,37 +106,30 @@ pub(crate) fn multiple_with_statements( } } - if let Some((is_async, items, body)) = next_with(with_body) { - if is_async != with_stmt.is_async_with_stmt() { + if let Some((is_async, items, _body)) = next_with(&with_stmt.body) { + if is_async != with_stmt.is_async { // One of the statements is an async with, while the other is not, // we can't merge those statements. return; } - let last_item = items.last().expect("Expected items to be non-empty"); - let colon = first_colon_range( - TextRange::new( - last_item - .optional_vars - .as_ref() - .map_or(last_item.context_expr.end(), |v| v.end()), - body.first().expect("Expected body to be non-empty").start(), - ), - checker.locator().contents(), - ); + let Some(colon) = items.last().and_then(|item| { + SimpleTokenizer::starts_at(item.end(), checker.locator().contents()) + .skip_trivia() + .find(|token| token.kind == SimpleTokenKind::Colon) + }) else { + return; + }; let mut diagnostic = Diagnostic::new( MultipleWithStatements, - colon.map_or_else( - || with_stmt.range(), - |colon| TextRange::new(with_stmt.start(), colon.end()), - ), + TextRange::new(with_stmt.start(), colon.end()), ); if checker.patch(diagnostic.kind.rule()) { if !checker .indexer() .comment_ranges() - .intersects(TextRange::new(with_stmt.start(), with_body[0].start())) + .intersects(TextRange::new(with_stmt.start(), with_stmt.body[0].start())) { match fix_with::fix_multiple_with_statements( checker.locator(), diff --git a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs index d5dc5ca9d8289..36d1f6eb962d8 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/fix_with.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Result}; use libcst_native::{CompoundStatement, Statement, Suite, With}; -use ruff_python_ast::Ranged; +use ruff_python_ast::{self as ast, Ranged}; use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::Edit; @@ -14,15 +14,15 @@ use crate::cst::matchers::{match_function_def, match_indented_block, match_state pub(crate) fn fix_multiple_with_statements( locator: &Locator, stylist: &Stylist, - stmt: &ruff_python_ast::Stmt, + with_stmt: &ast::StmtWith, ) -> Result { // Infer the indentation of the outer block. - let Some(outer_indent) = whitespace::indentation(locator, stmt) else { + let Some(outer_indent) = whitespace::indentation(locator, with_stmt) else { bail!("Unable to fix multiline statement"); }; // Extract the module text. - let contents = locator.lines(stmt.range()); + let contents = locator.lines(with_stmt.range()); // If the block is indented, "embed" it in a function definition, to preserve // indentation while retaining valid source code. (We'll strip the prefix later @@ -82,7 +82,7 @@ pub(crate) fn fix_multiple_with_statements( .to_string() }; - let range = locator.lines_range(stmt.range()); + let range = locator.lines_range(with_stmt.range()); Ok(Edit::range_replacement(contents, range)) } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs index d77a6479a5860..ac25976452be3 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -1,16 +1,12 @@ -use anyhow::Result; -use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged}; -use ruff_text_size::TextRange; - use ruff_diagnostics::Edit; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_codegen::Stylist; -use ruff_source_file::Locator; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::{self as ast, Arguments, CmpOp, Comprehension, Expr, Ranged}; +use ruff_text_size::TextRange; -use crate::autofix::codemods::CodegenStylist; use crate::checkers::ast::Checker; -use crate::cst::matchers::{match_attribute, match_call_mut, match_expression}; use crate::registry::AsRule; /// ## What it does @@ -67,12 +63,11 @@ fn key_in_dict( left: &Expr, right: &Expr, operator: CmpOp, - range: TextRange, + parent: AnyNodeRef, ) { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: Arguments { args, keywords, .. }, range: _, }) = &right else { @@ -96,18 +91,21 @@ fn key_in_dict( // ``` if value .as_name_expr() - .map_or(false, |name| matches!(name.id.as_str(), "self")) + .is_some_and(|name| matches!(name.id.as_str(), "self")) { return; } - // Slice exact content to preserve formatting. - let left_content = checker.locator().slice(left.range()); - let Ok(value_content) = - value_content_for_key_in_dict(checker.locator(), checker.stylist(), right) - else { - return; - }; + // Extract the exact range of the left and right expressions. + let left_range = parenthesized_range(left.into(), parent, checker.locator().contents()) + .unwrap_or(left.range()); + let right_range = parenthesized_range(right.into(), parent, checker.locator().contents()) + .unwrap_or(right.range()); + let value_range = parenthesized_range(value.into(), parent, checker.locator().contents()) + .unwrap_or(value.range()); + + let left_content = checker.locator().slice(left_range); + let value_content = checker.locator().slice(value_range); let mut diagnostic = Diagnostic::new( InDictKeys { @@ -115,37 +113,42 @@ fn key_in_dict( dict: value_content.to_string(), operator: operator.as_str().to_string(), }, - range, + TextRange::new(left_range.start(), right_range.end()), ); if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - value_content, - right.range(), + value_content.to_string(), + right_range, ))); } checker.diagnostics.push(diagnostic); } -/// SIM118 in a for loop -pub(crate) fn key_in_dict_for(checker: &mut Checker, target: &Expr, iter: &Expr) { +/// SIM118 in a `for` loop. +pub(crate) fn key_in_dict_for(checker: &mut Checker, for_stmt: &ast::StmtFor) { key_in_dict( checker, - target, - iter, + &for_stmt.target, + &for_stmt.iter, CmpOp::In, - TextRange::new(target.start(), iter.end()), + for_stmt.into(), ); } -/// SIM118 in a comparison -pub(crate) fn key_in_dict_compare( - checker: &mut Checker, - expr: &Expr, - left: &Expr, - ops: &[CmpOp], - comparators: &[Expr], -) { - let [op] = ops else { +/// SIM118 in a comprehension. +pub(crate) fn key_in_dict_comprehension(checker: &mut Checker, comprehension: &Comprehension) { + key_in_dict( + checker, + &comprehension.target, + &comprehension.iter, + CmpOp::In, + comprehension.into(), + ); +} + +/// SIM118 in a comparison. +pub(crate) fn key_in_dict_compare(checker: &mut Checker, compare: &ast::ExprCompare) { + let [op] = compare.ops.as_slice() else { return; }; @@ -153,21 +156,9 @@ pub(crate) fn key_in_dict_compare( return; } - let [right] = comparators else { + let [right] = compare.comparators.as_slice() else { return; }; - key_in_dict(checker, left, right, *op, expr.range()); -} - -fn value_content_for_key_in_dict( - locator: &Locator, - stylist: &Stylist, - expr: &Expr, -) -> Result { - let content = locator.slice(expr.range()); - let mut expression = match_expression(content)?; - let call = match_call_mut(&mut expression)?; - let attribute = match_attribute(&mut call.func)?; - Ok(attribute.value.codegen_stylist(stylist)) + key_in_dict(checker, &compare.left, right, *op, compare.into()); } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs index 02c2d392570df..5fd3a79c6d776 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs @@ -43,7 +43,7 @@ impl Violation for OpenFileWithContextHandler { /// Return `true` if the current expression is nested in an `await /// exit_stack.enter_async_context` call. fn match_async_exit_stack(semantic: &SemanticModel) -> bool { - let Some(expr) = semantic.expr_grandparent() else { + let Some(expr) = semantic.current_expression_grandparent() else { return false; }; let Expr::Await(ast::ExprAwait { value, range: _ }) = expr else { @@ -58,11 +58,11 @@ fn match_async_exit_stack(semantic: &SemanticModel) -> bool { if attr != "enter_async_context" { return false; } - for parent in semantic.parents() { + for parent in semantic.current_statements() { if let Stmt::With(ast::StmtWith { items, .. }) = parent { for item in items { if let Expr::Call(ast::ExprCall { func, .. }) = &item.context_expr { - if semantic.resolve_call_path(func).map_or(false, |call_path| { + if semantic.resolve_call_path(func).is_some_and(|call_path| { matches!(call_path.as_slice(), ["contextlib", "AsyncExitStack"]) }) { return true; @@ -77,7 +77,7 @@ fn match_async_exit_stack(semantic: &SemanticModel) -> bool { /// Return `true` if the current expression is nested in an /// `exit_stack.enter_context` call. fn match_exit_stack(semantic: &SemanticModel) -> bool { - let Some(expr) = semantic.expr_parent() else { + let Some(expr) = semantic.current_expression_parent() else { return false; }; let Expr::Call(ast::ExprCall { func, .. }) = expr else { @@ -89,11 +89,11 @@ fn match_exit_stack(semantic: &SemanticModel) -> bool { if attr != "enter_context" { return false; } - for parent in semantic.parents() { + for parent in semantic.current_statements() { if let Stmt::With(ast::StmtWith { items, .. }) = parent { for item in items { if let Expr::Call(ast::ExprCall { func, .. }) = &item.context_expr { - if semantic.resolve_call_path(func).map_or(false, |call_path| { + if semantic.resolve_call_path(func).is_some_and(|call_path| { matches!(call_path.as_slice(), ["contextlib", "ExitStack"]) }) { return true; @@ -114,9 +114,7 @@ fn is_open(checker: &mut Checker, func: &Expr) -> bool { Expr::Call(ast::ExprCall { func, .. }) => checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pathlib", "Path"]) - }), + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pathlib", "Path"])), _ => false, } } @@ -135,7 +133,7 @@ pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) } // Ex) `with open("foo.txt") as f: ...` - if checker.semantic().stmt().is_with_stmt() { + if checker.semantic().current_statement().is_with_stmt() { return; } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index efae2e7923dbf..6246da0da370a 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -1,5 +1,6 @@ use ruff_python_ast::{ - self as ast, CmpOp, Comprehension, Constant, Expr, ExprContext, Ranged, Stmt, UnaryOp, + self as ast, Arguments, CmpOp, Comprehension, Constant, Expr, ExprContext, Ranged, Stmt, + UnaryOp, }; use ruff_text_size::TextRange; @@ -59,7 +60,7 @@ impl Violation for ReimplementedBuiltin { /// SIM110, SIM111 pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) { - if !checker.semantic().scope().kind.is_any_function() { + if !checker.semantic().current_scope().kind.is_function() { return; } @@ -72,7 +73,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) { // - `for` loop with an `else: return True` or `else: return False`. // - `for` loop followed by `return True` or `return False`. let Some(terminal) = match_else_return(stmt).or_else(|| { - let parent = checker.semantic().stmt_parent()?; + let parent = checker.semantic().current_statement_parent()?; let suite = traversal::suite(stmt, parent)?; let sibling = traversal::next_sibling(stmt, suite)?; match_sibling_return(stmt, sibling) @@ -266,13 +267,10 @@ fn match_loop(stmt: &Stmt) -> Option { else { return None; }; - if nested_body.len() != 1 { - return None; - } if !nested_elif_else_clauses.is_empty() { return None; } - let Stmt::Return(ast::StmtReturn { value, range: _ }) = &nested_body[0] else { + let [Stmt::Return(ast::StmtReturn { value, range: _ })] = nested_body.as_slice() else { return None; }; let Some(value) = value else { @@ -394,8 +392,11 @@ fn return_stmt(id: &str, test: &Expr, target: &Expr, iter: &Expr, generator: Gen }; let node2 = ast::ExprCall { func: Box::new(node1.into()), - args: vec![node.into()], - keywords: vec![], + arguments: Arguments { + args: vec![node.into()], + keywords: vec![], + range: TextRange::default(), + }, range: TextRange::default(), }; let node3 = ast::StmtReturn { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs index 673925a416a93..f65dd7665d3df 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -1,16 +1,16 @@ use anyhow::Result; use libcst_native::CompOp; -use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged, UnaryOp}; -use crate::autofix::codemods::CodegenStylist; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged, UnaryOp}; use ruff_python_codegen::Stylist; use ruff_python_stdlib::str::{self}; use ruff_source_file::Locator; +use crate::autofix::snippet::SourceCodeSnippet; use crate::checkers::ast::Checker; -use crate::cst::matchers::{match_comparison, match_expression}; +use crate::cst::matchers::{match_comparison, transform_expression}; use crate::registry::AsRule; /// ## What it does @@ -45,7 +45,7 @@ use crate::registry::AsRule; /// - [Python documentation: Assignment statements](https://docs.python.org/3/reference/simple_stmts.html#assignment-statements) #[violation] pub struct YodaConditions { - pub suggestion: Option, + suggestion: Option, } impl Violation for YodaConditions { @@ -54,7 +54,10 @@ impl Violation for YodaConditions { #[derive_message_formats] fn message(&self) -> String { let YodaConditions { suggestion } = self; - if let Some(suggestion) = suggestion { + if let Some(suggestion) = suggestion + .as_ref() + .and_then(SourceCodeSnippet::full_display) + { format!("Yoda conditions are discouraged, use `{suggestion}` instead") } else { format!("Yoda conditions are discouraged") @@ -63,9 +66,13 @@ impl Violation for YodaConditions { fn autofix_title(&self) -> Option { let YodaConditions { suggestion } = self; - suggestion - .as_ref() - .map(|suggestion| format!("Replace Yoda condition with `{suggestion}`")) + suggestion.as_ref().map(|suggestion| { + if let Some(suggestion) = suggestion.full_display() { + format!("Replace Yoda condition with `{suggestion}`") + } else { + format!("Replace Yoda condition") + } + }) } } @@ -88,68 +95,69 @@ fn is_constant_like(expr: &Expr) -> bool { /// Generate a fix to reverse a comparison. fn reverse_comparison(expr: &Expr, locator: &Locator, stylist: &Stylist) -> Result { let range = expr.range(); - let contents = locator.slice(range); - - let mut expression = match_expression(contents)?; - let comparison = match_comparison(&mut expression)?; - - let left = (*comparison.left).clone(); - - // Copy the right side to the left side. - comparison.left = Box::new(comparison.comparisons[0].comparator.clone()); - - // Copy the left side to the right side. - comparison.comparisons[0].comparator = left; - - // Reverse the operator. - let op = comparison.comparisons[0].operator.clone(); - comparison.comparisons[0].operator = match op { - CompOp::LessThan { - whitespace_before, - whitespace_after, - } => CompOp::GreaterThan { - whitespace_before, - whitespace_after, - }, - CompOp::GreaterThan { - whitespace_before, - whitespace_after, - } => CompOp::LessThan { - whitespace_before, - whitespace_after, - }, - CompOp::LessThanEqual { - whitespace_before, - whitespace_after, - } => CompOp::GreaterThanEqual { - whitespace_before, - whitespace_after, - }, - CompOp::GreaterThanEqual { - whitespace_before, - whitespace_after, - } => CompOp::LessThanEqual { - whitespace_before, - whitespace_after, - }, - CompOp::Equal { - whitespace_before, - whitespace_after, - } => CompOp::Equal { - whitespace_before, - whitespace_after, - }, - CompOp::NotEqual { - whitespace_before, - whitespace_after, - } => CompOp::NotEqual { - whitespace_before, - whitespace_after, - }, - _ => panic!("Expected comparison operator"), - }; + let source_code = locator.slice(range); + + transform_expression(source_code, stylist, |mut expression| { + let comparison = match_comparison(&mut expression)?; + + let left = (*comparison.left).clone(); + + // Copy the right side to the left side. + comparison.left = Box::new(comparison.comparisons[0].comparator.clone()); + + // Copy the left side to the right side. + comparison.comparisons[0].comparator = left; + + // Reverse the operator. + let op = comparison.comparisons[0].operator.clone(); + comparison.comparisons[0].operator = match op { + CompOp::LessThan { + whitespace_before, + whitespace_after, + } => CompOp::GreaterThan { + whitespace_before, + whitespace_after, + }, + CompOp::GreaterThan { + whitespace_before, + whitespace_after, + } => CompOp::LessThan { + whitespace_before, + whitespace_after, + }, + CompOp::LessThanEqual { + whitespace_before, + whitespace_after, + } => CompOp::GreaterThanEqual { + whitespace_before, + whitespace_after, + }, + CompOp::GreaterThanEqual { + whitespace_before, + whitespace_after, + } => CompOp::LessThanEqual { + whitespace_before, + whitespace_after, + }, + CompOp::Equal { + whitespace_before, + whitespace_after, + } => CompOp::Equal { + whitespace_before, + whitespace_after, + }, + CompOp::NotEqual { + whitespace_before, + whitespace_after, + } => CompOp::NotEqual { + whitespace_before, + whitespace_after, + }, + _ => panic!("Expected comparison operator"), + }; - Ok(expression.codegen_stylist(stylist)) + Ok(expression) + }) } /// SIM300 @@ -178,7 +186,7 @@ pub(crate) fn yoda_conditions( if let Ok(suggestion) = reverse_comparison(expr, checker.locator(), checker.stylist()) { let mut diagnostic = Diagnostic::new( YodaConditions { - suggestion: Some(suggestion.to_string()), + suggestion: Some(SourceCodeSnippet::new(suggestion.clone())), }, expr.range(), ); diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap index 05cdf5c898408..09dac258018f1 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM118_SIM118.py.snap @@ -274,7 +274,7 @@ SIM118.py:32:1: SIM118 [*] Use `key in (obj or {})` instead of `key in (obj or { 32 | key in (obj or {}).keys() # SIM118 | ^^^^^^^^^^^^^^^^^^^^^^^^^ SIM118 33 | -34 | from typing import KeysView +34 | (key) in (obj or {}).keys() # SIM118 | = help: Convert to `key in (obj or {})` @@ -285,7 +285,28 @@ SIM118.py:32:1: SIM118 [*] Use `key in (obj or {})` instead of `key in (obj or { 32 |-key in (obj or {}).keys() # SIM118 32 |+key in (obj or {}) # SIM118 33 33 | -34 34 | from typing import KeysView +34 34 | (key) in (obj or {}).keys() # SIM118 35 35 | +SIM118.py:34:1: SIM118 [*] Use `(key) in (obj or {})` instead of `(key) in (obj or {}).keys()` + | +32 | key in (obj or {}).keys() # SIM118 +33 | +34 | (key) in (obj or {}).keys() # SIM118 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM118 +35 | +36 | from typing import KeysView + | + = help: Convert to `(key) in (obj or {})` + +ℹ Suggested fix +31 31 | +32 32 | key in (obj or {}).keys() # SIM118 +33 33 | +34 |-(key) in (obj or {}).keys() # SIM118 + 34 |+(key) in (obj or {}) # SIM118 +35 35 | +36 36 | from typing import KeysView +37 37 | + diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM300_SIM300.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM300_SIM300.py.snap index 38307e22c2f73..50c2af9f8c7cc 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM300_SIM300.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM300_SIM300.py.snap @@ -290,7 +290,7 @@ SIM300.py:15:1: SIM300 [*] Yoda conditions are discouraged, use `(number - 100) 17 17 | 18 18 | # OK -SIM300.py:16:1: SIM300 [*] Yoda conditions are discouraged, use `(60 * 60) < SomeClass().settings.SOME_CONSTANT_VALUE` instead +SIM300.py:16:1: SIM300 [*] Yoda conditions are discouraged | 14 | JediOrder.YODA == age # SIM300 15 | 0 < (number - 100) # SIM300 @@ -299,7 +299,7 @@ SIM300.py:16:1: SIM300 [*] Yoda conditions are discouraged, use `(60 * 60) < Som 17 | 18 | # OK | - = help: Replace Yoda condition with `(60 * 60) < SomeClass().settings.SOME_CONSTANT_VALUE` + = help: Replace Yoda condition ℹ Fix 13 13 | YODA >= age # SIM300 diff --git a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_namedtuple_subclass.rs b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_namedtuple_subclass.rs index 4497d7e4d9d9d..bffa54d55a72e 100644 --- a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_namedtuple_subclass.rs +++ b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_namedtuple_subclass.rs @@ -1,5 +1,5 @@ use ruff_python_ast as ast; -use ruff_python_ast::{Expr, StmtClassDef}; +use ruff_python_ast::{Arguments, Expr, StmtClassDef}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -63,16 +63,18 @@ pub(crate) fn no_slots_in_namedtuple_subclass( stmt: &Stmt, class: &StmtClassDef, ) { - if class.bases.iter().any(|base| { + let Some(Arguments { args: bases, .. }) = class.arguments.as_deref() else { + return; + }; + + if bases.iter().any(|base| { let Expr::Call(ast::ExprCall { func, .. }) = base else { return false; }; checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["collections", "namedtuple"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["collections", "namedtuple"])) }) { if !has_slots(&class.body) { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_str_subclass.rs b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_str_subclass.rs index fca7c9c9024da..c72057ea648f3 100644 --- a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_str_subclass.rs +++ b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_str_subclass.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Expr, Stmt, StmtClassDef}; +use ruff_python_ast::{Arguments, Expr, Stmt, StmtClassDef}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -51,7 +51,11 @@ impl Violation for NoSlotsInStrSubclass { /// SLOT000 pub(crate) fn no_slots_in_str_subclass(checker: &mut Checker, stmt: &Stmt, class: &StmtClassDef) { - if is_str_subclass(&class.bases, checker.semantic()) { + let Some(Arguments { args: bases, .. }) = class.arguments.as_deref() else { + return; + }; + + if is_str_subclass(bases, checker.semantic()) { if !has_slots(&class.body) { checker .diagnostics @@ -62,10 +66,10 @@ pub(crate) fn no_slots_in_str_subclass(checker: &mut Checker, stmt: &Stmt, class /// Return `true` if the class is a subclass of `str`, but _not_ a subclass of `enum.Enum`, /// `enum.IntEnum`, etc. -fn is_str_subclass(bases: &[Expr], model: &SemanticModel) -> bool { +fn is_str_subclass(bases: &[Expr], semantic: &SemanticModel) -> bool { let mut is_str_subclass = false; for base in bases { - if let Some(call_path) = model.resolve_call_path(base) { + if let Some(call_path) = semantic.resolve_call_path(base) { match call_path.as_slice() { ["" | "builtins", "str"] => { is_str_subclass = true; diff --git a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_tuple_subclass.rs b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_tuple_subclass.rs index 7ff26baf7a45d..c0f7a0d897564 100644 --- a/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_tuple_subclass.rs +++ b/crates/ruff/src/rules/flake8_slots/rules/no_slots_in_tuple_subclass.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Stmt, StmtClassDef}; +use ruff_python_ast::{Arguments, Stmt, StmtClassDef}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -51,11 +51,15 @@ impl Violation for NoSlotsInTupleSubclass { /// SLOT001 pub(crate) fn no_slots_in_tuple_subclass(checker: &mut Checker, stmt: &Stmt, class: &StmtClassDef) { - if class.bases.iter().any(|base| { + let Some(Arguments { args: bases, .. }) = class.arguments.as_deref() else { + return; + }; + + if bases.iter().any(|base| { checker .semantic() .resolve_call_path(map_subscript(base)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["" | "builtins", "tuple"]) || checker .semantic() diff --git a/crates/ruff/src/rules/flake8_tidy_imports/matchers.rs b/crates/ruff/src/rules/flake8_tidy_imports/matchers.rs new file mode 100644 index 0000000000000..a991280003299 --- /dev/null +++ b/crates/ruff/src/rules/flake8_tidy_imports/matchers.rs @@ -0,0 +1,75 @@ +/// Match an imported member against the ban policy. For example, given `from foo import bar`, +/// `foo` is the module and `bar` is the member. Performs an exact match. +#[derive(Debug)] +pub(crate) struct MatchName<'a> { + pub(crate) module: &'a str, + pub(crate) member: &'a str, +} + +impl MatchName<'_> { + fn is_match(&self, banned_module: &str) -> bool { + // Ex) Match banned `foo.bar` to import `foo.bar`, without allocating, assuming that + // `module` is `foo`, `member` is `bar`, and `banned_module` is `foo.bar`. + banned_module + .strip_prefix(self.module) + .and_then(|banned_module| banned_module.strip_prefix('.')) + .and_then(|banned_module| banned_module.strip_prefix(self.member)) + .is_some_and(str::is_empty) + } +} + +/// Match an imported module against the ban policy. For example, given `import foo.bar`, +/// `foo.bar` is the module. Matches against the module name or any of its parents. +#[derive(Debug)] +pub(crate) struct MatchNameOrParent<'a> { + pub(crate) module: &'a str, +} + +impl MatchNameOrParent<'_> { + fn is_match(&self, banned_module: &str) -> bool { + // Ex) Match banned `foo` to import `foo`. + if self.module == banned_module { + return true; + } + + // Ex) Match banned `foo` to import `foo.bar`. + if self + .module + .strip_prefix(banned_module) + .is_some_and(|suffix| suffix.starts_with('.')) + { + return true; + } + + false + } +} + +#[derive(Debug)] +pub(crate) enum NameMatchPolicy<'a> { + /// Only match an exact module name (e.g., given `import foo.bar`, only match `foo.bar`). + MatchName(MatchName<'a>), + /// Match an exact module name or any of its parents (e.g., given `import foo.bar`, match + /// `foo.bar` or `foo`). + MatchNameOrParent(MatchNameOrParent<'a>), +} + +impl NameMatchPolicy<'_> { + pub(crate) fn find<'a>(&self, banned_modules: impl Iterator) -> Option { + for banned_module in banned_modules { + match self { + NameMatchPolicy::MatchName(matcher) => { + if matcher.is_match(banned_module) { + return Some(banned_module.to_string()); + } + } + NameMatchPolicy::MatchNameOrParent(matcher) => { + if matcher.is_match(banned_module) { + return Some(banned_module.to_string()); + } + } + } + } + None + } +} diff --git a/crates/ruff/src/rules/flake8_tidy_imports/mod.rs b/crates/ruff/src/rules/flake8_tidy_imports/mod.rs index 8686f3971c06c..302640f4f8df1 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/mod.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/mod.rs @@ -1,4 +1,5 @@ //! Rules from [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/). +pub(crate) mod matchers; pub mod options; pub(crate) mod rules; pub mod settings; @@ -124,4 +125,23 @@ mod tests { assert_messages!(diagnostics); Ok(()) } + + #[test] + fn banned_module_level_imports() -> Result<()> { + let diagnostics = test_path( + Path::new("flake8_tidy_imports/TID253.py"), + &Settings { + flake8_tidy_imports: flake8_tidy_imports::settings::Settings { + banned_module_level_imports: vec![ + "torch".to_string(), + "tensorflow".to_string(), + ], + ..Default::default() + }, + ..Settings::for_rules(vec![Rule::BannedModuleLevelImports]) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } } diff --git a/crates/ruff/src/rules/flake8_tidy_imports/options.rs b/crates/ruff/src/rules/flake8_tidy_imports/options.rs index 6f3eb99fcb631..a2bc84c300374 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/options.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/options.rs @@ -41,6 +41,19 @@ pub struct Options { /// Note that this rule is only meant to flag accidental uses, /// and can be circumvented via `eval` or `importlib`. pub banned_api: Option>, + #[option( + default = r#"[]"#, + value_type = r#"list[str]"#, + example = r#" + # Ban certain modules from being imported at module level, instead requiring + # that they're imported lazily (e.g., within a function definition). + banned-module-level-imports = ["torch", "tensorflow"] + "# + )] + /// List of specific modules that may not be imported at module level, and should instead be + /// imported lazily (e.g., within a function definition, or an `if TYPE_CHECKING:` + /// block, or some other nested context). + pub banned_module_level_imports: Option>, } impl From for Settings { @@ -48,6 +61,7 @@ impl From for Settings { Self { ban_relative_imports: options.ban_relative_imports.unwrap_or(Strictness::Parents), banned_api: options.banned_api.unwrap_or_default(), + banned_module_level_imports: options.banned_module_level_imports.unwrap_or_default(), } } } @@ -57,6 +71,7 @@ impl From for Options { Self { ban_relative_imports: Some(settings.ban_relative_imports), banned_api: Some(settings.banned_api), + banned_module_level_imports: Some(settings.banned_module_level_imports), } } } diff --git a/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_api.rs b/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_api.rs index e214802ded4f4..a2e8e8ad255b0 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_api.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_api.rs @@ -5,6 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::from_qualified_name; use crate::checkers::ast::Checker; +use crate::rules::flake8_tidy_imports::matchers::NameMatchPolicy; /// ## What it does /// Checks for banned imports. @@ -38,45 +39,17 @@ impl Violation for BannedApi { } /// TID251 -pub(crate) fn name_is_banned(checker: &mut Checker, name: String, located: &T) -where - T: Ranged, -{ +pub(crate) fn banned_api(checker: &mut Checker, policy: &NameMatchPolicy, node: &T) { let banned_api = &checker.settings.flake8_tidy_imports.banned_api; - if let Some(ban) = banned_api.get(&name) { - checker.diagnostics.push(Diagnostic::new( - BannedApi { - name, - message: ban.msg.to_string(), - }, - located.range(), - )); - } -} - -/// TID251 -pub(crate) fn name_or_parent_is_banned(checker: &mut Checker, name: &str, located: &T) -where - T: Ranged, -{ - let banned_api = &checker.settings.flake8_tidy_imports.banned_api; - let mut name = name; - loop { - if let Some(ban) = banned_api.get(name) { + if let Some(banned_module) = policy.find(banned_api.keys().map(AsRef::as_ref)) { + if let Some(reason) = banned_api.get(&banned_module) { checker.diagnostics.push(Diagnostic::new( BannedApi { - name: name.to_string(), - message: ban.msg.to_string(), + name: banned_module, + message: reason.msg.to_string(), }, - located.range(), + node.range(), )); - return; - } - match name.rfind('.') { - Some(idx) => { - name = &name[..idx]; - } - None => return, } } } diff --git a/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_module_level_imports.rs b/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_module_level_imports.rs new file mode 100644 index 0000000000000..283b8f90a4abe --- /dev/null +++ b/crates/ruff/src/rules/flake8_tidy_imports/rules/banned_module_level_imports.rs @@ -0,0 +1,80 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; + +use crate::checkers::ast::Checker; +use crate::rules::flake8_tidy_imports::matchers::NameMatchPolicy; + +/// ## What it does +/// Checks for module-level imports that should instead be imported lazily +/// (e.g., within a function definition, or an `if TYPE_CHECKING:` block, or +/// some other nested context). +/// +/// ## Why is this bad? +/// Some modules are expensive to import. For example, importing `torch` or +/// `tensorflow` can introduce a noticeable delay in the startup time of a +/// Python program. +/// +/// In such cases, you may want to enforce that the module is imported lazily +/// as needed, rather than at the top of the file. This could involve inlining +/// the import into the function that uses it, rather than importing it +/// unconditionally, to ensure that the module is only imported when necessary. +/// +/// ## Example +/// ```python +/// import tensorflow as tf +/// +/// +/// def show_version(): +/// print(tf.__version__) +/// ``` +/// +/// Use instead: +/// ```python +/// def show_version(): +/// import tensorflow as tf +/// +/// print(tf.__version__) +/// ``` +/// +/// ## Options +/// - `flake8-tidy-imports.banned-module-level-imports` +#[violation] +pub struct BannedModuleLevelImports { + name: String, +} + +impl Violation for BannedModuleLevelImports { + #[derive_message_formats] + fn message(&self) -> String { + let BannedModuleLevelImports { name } = self; + format!("`{name}` is banned at the module level") + } +} + +/// TID253 +pub(crate) fn banned_module_level_imports( + checker: &mut Checker, + policy: &NameMatchPolicy, + node: &T, +) { + if !checker.semantic().at_top_level() { + return; + } + + if let Some(banned_module) = policy.find( + checker + .settings + .flake8_tidy_imports + .banned_module_level_imports + .iter() + .map(AsRef::as_ref), + ) { + checker.diagnostics.push(Diagnostic::new( + BannedModuleLevelImports { + name: banned_module, + }, + node.range(), + )); + } +} diff --git a/crates/ruff/src/rules/flake8_tidy_imports/rules/mod.rs b/crates/ruff/src/rules/flake8_tidy_imports/rules/mod.rs index 660116d718a84..a9c8e631d9e8e 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/rules/mod.rs @@ -1,5 +1,7 @@ pub(crate) use banned_api::*; +pub(crate) use banned_module_level_imports::*; pub(crate) use relative_imports::*; mod banned_api; +mod banned_module_level_imports; mod relative_imports; diff --git a/crates/ruff/src/rules/flake8_tidy_imports/settings.rs b/crates/ruff/src/rules/flake8_tidy_imports/settings.rs index 90b2843280f27..a1267fbc9b8a8 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/settings.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/settings.rs @@ -26,4 +26,5 @@ pub enum Strictness { pub struct Settings { pub ban_relative_imports: Strictness, pub banned_api: FxHashMap, + pub banned_module_level_imports: Vec, } diff --git a/crates/ruff/src/rules/flake8_tidy_imports/snapshots/ruff__rules__flake8_tidy_imports__tests__banned_module_level_imports.snap b/crates/ruff/src/rules/flake8_tidy_imports/snapshots/ruff__rules__flake8_tidy_imports__tests__banned_module_level_imports.snap new file mode 100644 index 0000000000000..40bb5c9f5852d --- /dev/null +++ b/crates/ruff/src/rules/flake8_tidy_imports/snapshots/ruff__rules__flake8_tidy_imports__tests__banned_module_level_imports.snap @@ -0,0 +1,81 @@ +--- +source: crates/ruff/src/rules/flake8_tidy_imports/mod.rs +--- +TID253.py:2:8: TID253 `torch` is banned at the module level + | +1 | ## Banned modules ## +2 | import torch + | ^^^^^ TID253 +3 | +4 | from torch import * + | + +TID253.py:4:1: TID253 `torch` is banned at the module level + | +2 | import torch +3 | +4 | from torch import * + | ^^^^^^^^^^^^^^^^^^^ TID253 +5 | +6 | from tensorflow import a, b, c + | + +TID253.py:6:1: TID253 `tensorflow` is banned at the module level + | +4 | from torch import * +5 | +6 | from tensorflow import a, b, c + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TID253 +7 | +8 | import torch as torch_wearing_a_trenchcoat + | + +TID253.py:8:8: TID253 `torch` is banned at the module level + | + 6 | from tensorflow import a, b, c + 7 | + 8 | import torch as torch_wearing_a_trenchcoat + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TID253 + 9 | +10 | # this should count as module level + | + +TID253.py:11:15: TID253 `tensorflow` is banned at the module level + | +10 | # this should count as module level +11 | x = 1; import tensorflow + | ^^^^^^^^^^ TID253 +12 | +13 | # banning a module also bans any submodules + | + +TID253.py:14:8: TID253 `torch` is banned at the module level + | +13 | # banning a module also bans any submodules +14 | import torch.foo.bar + | ^^^^^^^^^^^^^ TID253 +15 | +16 | from tensorflow.foo import bar + | + +TID253.py:16:1: TID253 `tensorflow` is banned at the module level + | +14 | import torch.foo.bar +15 | +16 | from tensorflow.foo import bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TID253 +17 | +18 | from torch.foo.bar import * + | + +TID253.py:18:1: TID253 `torch` is banned at the module level + | +16 | from tensorflow.foo import bar +17 | +18 | from torch.foo.bar import * + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ TID253 +19 | +20 | # unlike TID251, inline imports are *not* banned + | + + diff --git a/crates/ruff/src/rules/flake8_type_checking/helpers.rs b/crates/ruff/src/rules/flake8_type_checking/helpers.rs index 63115dbe040af..31b5c6d2c3c86 100644 --- a/crates/ruff/src/rules/flake8_type_checking/helpers.rs +++ b/crates/ruff/src/rules/flake8_type_checking/helpers.rs @@ -1,5 +1,3 @@ -use ruff_python_ast as ast; - use ruff_python_ast::call_path::from_qualified_name; use ruff_python_ast::helpers::map_callable; use ruff_python_semantic::{Binding, BindingKind, ScopeKind, SemanticModel}; @@ -37,34 +35,31 @@ pub(crate) fn runtime_evaluated( } fn runtime_evaluated_base_class(base_classes: &[String], semantic: &SemanticModel) -> bool { - if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = &semantic.scope().kind { - for base in bases { - if let Some(call_path) = semantic.resolve_call_path(base) { - if base_classes - .iter() - .any(|base_class| from_qualified_name(base_class) == call_path) - { - return true; - } - } - } - } - false + let ScopeKind::Class(class_def) = &semantic.current_scope().kind else { + return false; + }; + + class_def.bases().iter().any(|base| { + semantic.resolve_call_path(base).is_some_and(|call_path| { + base_classes + .iter() + .any(|base_class| from_qualified_name(base_class) == call_path) + }) + }) } fn runtime_evaluated_decorators(decorators: &[String], semantic: &SemanticModel) -> bool { - if let ScopeKind::Class(ast::StmtClassDef { decorator_list, .. }) = &semantic.scope().kind { - for decorator in decorator_list { - if let Some(call_path) = semantic.resolve_call_path(map_callable(&decorator.expression)) - { - if decorators + let ScopeKind::Class(class_def) = &semantic.current_scope().kind else { + return false; + }; + + class_def.decorator_list.iter().any(|decorator| { + semantic + .resolve_call_path(map_callable(&decorator.expression)) + .is_some_and(|call_path| { + decorators .iter() - .any(|decorator| from_qualified_name(decorator) == call_path) - { - return true; - } - } - } - } - false + .any(|base_class| from_qualified_name(base_class) == call_path) + }) + }) } diff --git a/crates/ruff/src/rules/flake8_type_checking/mod.rs b/crates/ruff/src/rules/flake8_type_checking/mod.rs index 3be76de290d7d..99a76cb890bd4 100644 --- a/crates/ruff/src/rules/flake8_type_checking/mod.rs +++ b/crates/ruff/src/rules/flake8_type_checking/mod.rs @@ -89,13 +89,20 @@ mod tests { Rule::TypingOnlyStandardLibraryImport, Path::new("runtime_evaluated_base_classes_3.py") )] + #[test_case( + Rule::TypingOnlyStandardLibraryImport, + Path::new("runtime_evaluated_base_classes_4.py") + )] fn runtime_evaluated_base_classes(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.as_ref(), path.to_string_lossy()); let diagnostics = test_path( Path::new("flake8_type_checking").join(path).as_path(), &settings::Settings { flake8_type_checking: super::settings::Settings { - runtime_evaluated_base_classes: vec!["pydantic.BaseModel".to_string()], + runtime_evaluated_base_classes: vec![ + "pydantic.BaseModel".to_string(), + "sqlalchemy.orm.DeclarativeBase".to_string(), + ], ..Default::default() }, ..settings::Settings::for_rule(rule_code) diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs index 5bb8533778b6a..eee9638e21c67 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs @@ -58,10 +58,12 @@ pub(crate) fn empty_type_checking_block(checker: &mut Checker, stmt: &ast::StmtI let mut diagnostic = Diagnostic::new(EmptyTypeCheckingBlock, stmt.range()); if checker.patch(diagnostic.kind.rule()) { // Delete the entire type-checking block. - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = autofix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::automatic(edit).isolate(checker.isolation(parent))); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs b/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs index ea4899c572292..a3a01523f3ad4 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs @@ -1,15 +1,18 @@ +use std::borrow::Cow; + use anyhow::Result; -use ruff_text_size::TextRange; use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{NodeId, ResolvedReferenceId, Scope}; +use ruff_python_ast::Ranged; +use ruff_python_semantic::{AnyImport, Imported, NodeId, ResolvedReferenceId, Scope}; +use ruff_text_size::TextRange; use crate::autofix; use crate::checkers::ast::Checker; use crate::codes::Rule; -use crate::importer::StmtImports; +use crate::importer::ImportedMembers; /// ## What it does /// Checks for runtime imports defined in a type-checking block. @@ -69,13 +72,13 @@ pub(crate) fn runtime_import_in_type_checking_block( diagnostics: &mut Vec, ) { // Collect all runtime imports by statement. - let mut errors_by_statement: FxHashMap> = FxHashMap::default(); - let mut ignores_by_statement: FxHashMap> = FxHashMap::default(); + let mut errors_by_statement: FxHashMap> = FxHashMap::default(); + let mut ignores_by_statement: FxHashMap> = FxHashMap::default(); for binding_id in scope.binding_ids() { let binding = checker.semantic().binding(binding_id); - let Some(qualified_name) = binding.qualified_name() else { + let Some(import) = binding.as_any_import() else { continue; }; @@ -92,19 +95,19 @@ pub(crate) fn runtime_import_in_type_checking_block( .is_runtime() }) { - let Some(stmt_id) = binding.source else { + let Some(node_id) = binding.source else { continue; }; - let import = Import { - qualified_name, + let import = ImportBinding { + import, reference_id, - range: binding.range, + range: binding.range(), parent_range: binding.parent_range(checker.semantic()), }; - if checker.rule_is_ignored(Rule::RuntimeImportInTypeCheckingBlock, import.range.start()) - || import.parent_range.map_or(false, |parent_range| { + if checker.rule_is_ignored(Rule::RuntimeImportInTypeCheckingBlock, import.start()) + || import.parent_range.is_some_and(|parent_range| { checker.rule_is_ignored( Rule::RuntimeImportInTypeCheckingBlock, parent_range.start(), @@ -112,26 +115,26 @@ pub(crate) fn runtime_import_in_type_checking_block( }) { ignores_by_statement - .entry(stmt_id) + .entry(node_id) .or_default() .push(import); } else { - errors_by_statement.entry(stmt_id).or_default().push(import); + errors_by_statement.entry(node_id).or_default().push(import); } } } // Generate a diagnostic for every import, but share a fix across all imports within the same // statement (excluding those that are ignored). - for (stmt_id, imports) in errors_by_statement { + for (node_id, imports) in errors_by_statement { let fix = if checker.patch(Rule::RuntimeImportInTypeCheckingBlock) { - fix_imports(checker, stmt_id, &imports).ok() + fix_imports(checker, node_id, &imports).ok() } else { None }; - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, .. @@ -139,7 +142,7 @@ pub(crate) fn runtime_import_in_type_checking_block( { let mut diagnostic = Diagnostic::new( RuntimeImportInTypeCheckingBlock { - qualified_name: qualified_name.to_string(), + qualified_name: import.qualified_name(), }, range, ); @@ -155,8 +158,8 @@ pub(crate) fn runtime_import_in_type_checking_block( // Separately, generate a diagnostic for every _ignored_ import, to ensure that the // suppression comments aren't marked as unused. - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, .. @@ -164,7 +167,7 @@ pub(crate) fn runtime_import_in_type_checking_block( { let mut diagnostic = Diagnostic::new( RuntimeImportInTypeCheckingBlock { - qualified_name: qualified_name.to_string(), + qualified_name: import.qualified_name(), }, range, ); @@ -176,9 +179,9 @@ pub(crate) fn runtime_import_in_type_checking_block( } /// A runtime-required import with its surrounding context. -struct Import<'a> { +struct ImportBinding<'a> { /// The qualified name of the import (e.g., `typing.List` for `from typing import List`). - qualified_name: &'a str, + import: AnyImport<'a>, /// The first reference to the imported symbol. reference_id: ResolvedReferenceId, /// The trimmed range of the import (e.g., `List` in `from typing import List`). @@ -187,28 +190,36 @@ struct Import<'a> { parent_range: Option, } +impl Ranged for ImportBinding<'_> { + fn range(&self) -> TextRange { + self.range + } +} + /// Generate a [`Fix`] to remove runtime imports from a type-checking block. -fn fix_imports(checker: &Checker, stmt_id: NodeId, imports: &[Import]) -> Result { - let stmt = checker.semantic().stmts[stmt_id]; - let parent = checker.semantic().stmts.parent(stmt); - let qualified_names: Vec<&str> = imports +fn fix_imports(checker: &Checker, node_id: NodeId, imports: &[ImportBinding]) -> Result { + let statement = checker.semantic().statement(node_id); + let parent = checker.semantic().parent_statement(node_id); + + let member_names: Vec> = imports .iter() - .map(|Import { qualified_name, .. }| *qualified_name) + .map(|ImportBinding { import, .. }| import) + .map(Imported::member_name) .collect(); // Find the first reference across all imports. let at = imports .iter() - .map(|Import { reference_id, .. }| { - checker.semantic().reference(*reference_id).range().start() + .map(|ImportBinding { reference_id, .. }| { + checker.semantic().reference(*reference_id).start() }) .min() .expect("Expected at least one import"); // Step 1) Remove the import. let remove_import_edit = autofix::edits::remove_unused_imports( - qualified_names.iter().copied(), - stmt, + member_names.iter().map(AsRef::as_ref), + statement, parent, checker.locator(), checker.stylist(), @@ -217,15 +228,16 @@ fn fix_imports(checker: &Checker, stmt_id: NodeId, imports: &[Import]) -> Result // Step 2) Add the import to the top-level. let add_import_edit = checker.importer().runtime_import_edit( - &StmtImports { - stmt, - qualified_names, + &ImportedMembers { + statement, + names: member_names.iter().map(AsRef::as_ref).collect(), }, at, )?; Ok( - Fix::suggested_edits(remove_import_edit, add_import_edit.into_edits()) - .isolate(checker.isolation(parent)), + Fix::suggested_edits(remove_import_edit, add_import_edit.into_edits()).isolate( + Checker::isolation(checker.semantic().parent_statement_id(node_id)), + ), ) } diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs b/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs index 4695395b417a8..abb1bff8efb6f 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs @@ -1,15 +1,18 @@ +use std::borrow::Cow; + use anyhow::Result; -use ruff_text_size::TextRange; use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, DiagnosticKind, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Binding, NodeId, ResolvedReferenceId, Scope}; +use ruff_python_ast::Ranged; +use ruff_python_semantic::{AnyImport, Binding, Imported, NodeId, ResolvedReferenceId, Scope}; +use ruff_text_size::TextRange; use crate::autofix; use crate::checkers::ast::Checker; use crate::codes::Rule; -use crate::importer::StmtImports; +use crate::importer::ImportedMembers; use crate::rules::isort::{categorize, ImportSection, ImportType}; /// ## What it does @@ -18,17 +21,25 @@ use crate::rules::isort::{categorize, ImportSection, ImportType}; /// /// ## Why is this bad? /// Unused imports add a performance overhead at runtime, and risk creating -/// import cycles. +/// import cycles. If an import is _only_ used in typing-only contexts, it can +/// instead be imported conditionally under an `if TYPE_CHECKING:` block to +/// minimize runtime overhead. +/// +/// If a class _requires_ that type annotations be available at runtime (as is +/// the case for Pydantic, SQLAlchemy, and other libraries), consider using +/// the [`flake8-type-checking.runtime-evaluated-base-classes`] and +/// [`flake8-type-checking.runtime-evaluated-decorators`] settings to mark them +/// as such. /// /// ## Example /// ```python /// from __future__ import annotations /// -/// import A +/// import local_module /// /// -/// def foo(a: A) -> int: -/// return len(a) +/// def func(sized: local_module.Container) -> int: +/// return len(sized) /// ``` /// /// Use instead: @@ -38,13 +49,17 @@ use crate::rules::isort::{categorize, ImportSection, ImportType}; /// from typing import TYPE_CHECKING /// /// if TYPE_CHECKING: -/// import A +/// import local_module /// /// -/// def foo(a: A) -> int: -/// return len(a) +/// def func(sized: local_module.Container) -> int: +/// return len(sized) /// ``` /// +/// ## Options +/// - `flake8-type-checking.runtime-evaluated-base-classes` +/// - `flake8-type-checking.runtime-evaluated-decorators` +/// /// ## References /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] @@ -74,7 +89,15 @@ impl Violation for TypingOnlyFirstPartyImport { /// /// ## Why is this bad? /// Unused imports add a performance overhead at runtime, and risk creating -/// import cycles. +/// import cycles. If an import is _only_ used in typing-only contexts, it can +/// instead be imported conditionally under an `if TYPE_CHECKING:` block to +/// minimize runtime overhead. +/// +/// If a class _requires_ that type annotations be available at runtime (as is +/// the case for Pydantic, SQLAlchemy, and other libraries), consider using +/// the [`flake8-type-checking.runtime-evaluated-base-classes`] and +/// [`flake8-type-checking.runtime-evaluated-decorators`] settings to mark them +/// as such. /// /// ## Example /// ```python @@ -83,7 +106,7 @@ impl Violation for TypingOnlyFirstPartyImport { /// import pandas as pd /// /// -/// def foo(df: pd.DataFrame) -> int: +/// def func(df: pd.DataFrame) -> int: /// return len(df) /// ``` /// @@ -97,10 +120,14 @@ impl Violation for TypingOnlyFirstPartyImport { /// import pandas as pd /// /// -/// def foo(df: pd.DataFrame) -> int: +/// def func(df: pd.DataFrame) -> int: /// return len(df) /// ``` /// +/// ## Options +/// - `flake8-type-checking.runtime-evaluated-base-classes` +/// - `flake8-type-checking.runtime-evaluated-decorators` +/// /// ## References /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] @@ -130,7 +157,15 @@ impl Violation for TypingOnlyThirdPartyImport { /// /// ## Why is this bad? /// Unused imports add a performance overhead at runtime, and risk creating -/// import cycles. +/// import cycles. If an import is _only_ used in typing-only contexts, it can +/// instead be imported conditionally under an `if TYPE_CHECKING:` block to +/// minimize runtime overhead. +/// +/// If a class _requires_ that type annotations be available at runtime (as is +/// the case for Pydantic, SQLAlchemy, and other libraries), consider using +/// the [`flake8-type-checking.runtime-evaluated-base-classes`] and +/// [`flake8-type-checking.runtime-evaluated-decorators`] settings to mark them +/// as such. /// /// ## Example /// ```python @@ -139,7 +174,7 @@ impl Violation for TypingOnlyThirdPartyImport { /// from pathlib import Path /// /// -/// def foo(path: Path) -> str: +/// def func(path: Path) -> str: /// return str(path) /// ``` /// @@ -153,10 +188,14 @@ impl Violation for TypingOnlyThirdPartyImport { /// from pathlib import Path /// /// -/// def foo(path: Path) -> str: +/// def func(path: Path) -> str: /// return str(path) /// ``` /// +/// ## Options +/// - `flake8-type-checking.runtime-evaluated-base-classes` +/// - `flake8-type-checking.runtime-evaluated-decorators` +/// /// ## References /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] @@ -188,9 +227,9 @@ pub(crate) fn typing_only_runtime_import( diagnostics: &mut Vec, ) { // Collect all typing-only imports by statement and import type. - let mut errors_by_statement: FxHashMap<(NodeId, ImportType), Vec> = + let mut errors_by_statement: FxHashMap<(NodeId, ImportType), Vec> = FxHashMap::default(); - let mut ignores_by_statement: FxHashMap<(NodeId, ImportType), Vec> = + let mut ignores_by_statement: FxHashMap<(NodeId, ImportType), Vec> = FxHashMap::default(); for binding_id in scope.binding_ids() { @@ -206,23 +245,10 @@ pub(crate) fn typing_only_runtime_import( continue; } - let Some(qualified_name) = binding.qualified_name() else { + let Some(import) = binding.as_any_import() else { continue; }; - if is_exempt( - qualified_name, - &checker - .settings - .flake8_type_checking - .exempt_modules - .iter() - .map(String::as_str) - .collect::>(), - ) { - continue; - } - let Some(reference_id) = binding.references.first().copied() else { continue; }; @@ -236,22 +262,28 @@ pub(crate) fn typing_only_runtime_import( .is_typing() }) { - // Extract the module base and level from the full name. - // Ex) `foo.bar.baz` -> `foo`, `0` - // Ex) `.foo.bar.baz` -> `foo`, `1` - let level = qualified_name - .chars() - .take_while(|c| *c == '.') - .count() - .try_into() - .unwrap(); + let qualified_name = import.qualified_name(); + + if is_exempt( + qualified_name.as_str(), + &checker + .settings + .flake8_type_checking + .exempt_modules + .iter() + .map(String::as_str) + .collect::>(), + ) { + continue; + } // Categorize the import, using coarse-grained categorization. let import_type = match categorize( - qualified_name, - Some(level), + qualified_name.as_str(), + None, &checker.settings.src, checker.package(), + checker.settings.isort.detect_same_package, &checker.settings.isort.known_modules, checker.settings.target_version, ) { @@ -271,29 +303,29 @@ pub(crate) fn typing_only_runtime_import( continue; } - let Some(stmt_id) = binding.source else { + let Some(node_id) = binding.source else { continue; }; - let import = Import { - qualified_name, + let import = ImportBinding { + import, reference_id, - range: binding.range, + range: binding.range(), parent_range: binding.parent_range(checker.semantic()), }; - if checker.rule_is_ignored(rule_for(import_type), import.range.start()) - || import.parent_range.map_or(false, |parent_range| { + if checker.rule_is_ignored(rule_for(import_type), import.start()) + || import.parent_range.is_some_and(|parent_range| { checker.rule_is_ignored(rule_for(import_type), parent_range.start()) }) { ignores_by_statement - .entry((stmt_id, import_type)) + .entry((node_id, import_type)) .or_default() .push(import); } else { errors_by_statement - .entry((stmt_id, import_type)) + .entry((node_id, import_type)) .or_default() .push(import); } @@ -302,24 +334,22 @@ pub(crate) fn typing_only_runtime_import( // Generate a diagnostic for every import, but share a fix across all imports within the same // statement (excluding those that are ignored). - for ((stmt_id, import_type), imports) in errors_by_statement { + for ((node_id, import_type), imports) in errors_by_statement { let fix = if checker.patch(rule_for(import_type)) { - fix_imports(checker, stmt_id, &imports).ok() + fix_imports(checker, node_id, &imports).ok() } else { None }; - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, .. } in imports { - let mut diagnostic = Diagnostic::new( - diagnostic_for(import_type, qualified_name.to_string()), - range, - ); + let mut diagnostic = + Diagnostic::new(diagnostic_for(import_type, import.qualified_name()), range); if let Some(range) = parent_range { diagnostic.set_parent(range.start()); } @@ -333,17 +363,15 @@ pub(crate) fn typing_only_runtime_import( // Separately, generate a diagnostic for every _ignored_ import, to ensure that the // suppression comments aren't marked as unused. for ((_, import_type), imports) in ignores_by_statement { - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, .. } in imports { - let mut diagnostic = Diagnostic::new( - diagnostic_for(import_type, qualified_name.to_string()), - range, - ); + let mut diagnostic = + Diagnostic::new(diagnostic_for(import_type, import.qualified_name()), range); if let Some(range) = parent_range { diagnostic.set_parent(range.start()); } @@ -353,9 +381,9 @@ pub(crate) fn typing_only_runtime_import( } /// A runtime-required import with its surrounding context. -struct Import<'a> { +struct ImportBinding<'a> { /// The qualified name of the import (e.g., `typing.List` for `from typing import List`). - qualified_name: &'a str, + import: AnyImport<'a>, /// The first reference to the imported symbol. reference_id: ResolvedReferenceId, /// The trimmed range of the import (e.g., `List` in `from typing import List`). @@ -364,6 +392,12 @@ struct Import<'a> { parent_range: Option, } +impl Ranged for ImportBinding<'_> { + fn range(&self) -> TextRange { + self.range + } +} + /// Return the [`Rule`] for the given import type. fn rule_for(import_type: ImportType) -> Rule { match import_type { @@ -386,13 +420,13 @@ fn diagnostic_for(import_type: ImportType, qualified_name: String) -> Diagnostic /// Return `true` if `this` is implicitly loaded via importing `that`. fn is_implicit_import(this: &Binding, that: &Binding) -> bool { - let Some(this_module) = this.module_name() else { + let Some(this_import) = this.as_any_import() else { return false; }; - let Some(that_module) = that.module_name() else { + let Some(that_import) = that.as_any_import() else { return false; }; - this_module == that_module + this_import.module_name() == that_import.module_name() } /// Return `true` if `name` is exempt from typing-only enforcement. @@ -412,27 +446,29 @@ fn is_exempt(name: &str, exempt_modules: &[&str]) -> bool { } /// Generate a [`Fix`] to remove typing-only imports from a runtime context. -fn fix_imports(checker: &Checker, stmt_id: NodeId, imports: &[Import]) -> Result { - let stmt = checker.semantic().stmts[stmt_id]; - let parent = checker.semantic().stmts.parent(stmt); - let qualified_names: Vec<&str> = imports +fn fix_imports(checker: &Checker, node_id: NodeId, imports: &[ImportBinding]) -> Result { + let statement = checker.semantic().statement(node_id); + let parent = checker.semantic().parent_statement(node_id); + + let member_names: Vec> = imports .iter() - .map(|Import { qualified_name, .. }| *qualified_name) + .map(|ImportBinding { import, .. }| import) + .map(Imported::member_name) .collect(); // Find the first reference across all imports. let at = imports .iter() - .map(|Import { reference_id, .. }| { - checker.semantic().reference(*reference_id).range().start() + .map(|ImportBinding { reference_id, .. }| { + checker.semantic().reference(*reference_id).start() }) .min() .expect("Expected at least one import"); // Step 1) Remove the import. let remove_import_edit = autofix::edits::remove_unused_imports( - qualified_names.iter().copied(), - stmt, + member_names.iter().map(AsRef::as_ref), + statement, parent, checker.locator(), checker.stylist(), @@ -441,16 +477,18 @@ fn fix_imports(checker: &Checker, stmt_id: NodeId, imports: &[Import]) -> Result // Step 2) Add the import to a `TYPE_CHECKING` block. let add_import_edit = checker.importer().typing_import_edit( - &StmtImports { - stmt, - qualified_names, + &ImportedMembers { + statement, + names: member_names.iter().map(AsRef::as_ref).collect(), }, at, checker.semantic(), + checker.source_type, )?; Ok( - Fix::suggested_edits(remove_import_edit, add_import_edit.into_edits()) - .isolate(checker.isolation(parent)), + Fix::suggested_edits(remove_import_edit, add_import_edit.into_edits()).isolate( + Checker::isolation(checker.semantic().parent_statement_id(node_id)), + ), ) } diff --git a/crates/ruff/src/rules/flake8_type_checking/settings.rs b/crates/ruff/src/rules/flake8_type_checking/settings.rs index 69cd913dae913..4e9871e5ec837 100644 --- a/crates/ruff/src/rules/flake8_type_checking/settings.rs +++ b/crates/ruff/src/rules/flake8_type_checking/settings.rs @@ -23,6 +23,7 @@ pub struct Options { )] /// Enforce TC001, TC002, and TC003 rules even when valid runtime imports /// are present for the same module. + /// /// See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option. pub strict: Option, #[option( @@ -39,11 +40,19 @@ pub struct Options { default = "[]", value_type = "list[str]", example = r#" - runtime-evaluated-base-classes = ["pydantic.BaseModel"] + runtime-evaluated-base-classes = ["pydantic.BaseModel", "sqlalchemy.orm.DeclarativeBase"] "# )] /// Exempt classes that list any of the enumerated classes as a base class /// from needing to be moved into type-checking blocks. + /// + /// Common examples include Pydantic's `pydantic.BaseModel` and SQLAlchemy's + /// `sqlalchemy.orm.DeclarativeBase`, but can also support user-defined + /// classes that inherit from those base classes. For example, if you define + /// a common `DeclarativeBase` subclass that's used throughout your project + /// (e.g., `class Base(DeclarativeBase) ...` in `base.py`), you can add it to + /// this list (`runtime-evaluated-base-classes = ["base.Base"]`) to exempt + /// models from being moved into type-checking blocks. pub runtime_evaluated_base_classes: Option>, #[option( default = "[]", diff --git a/crates/ruff/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__typing-only-standard-library-import_runtime_evaluated_base_classes_4.py.snap b/crates/ruff/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__typing-only-standard-library-import_runtime_evaluated_base_classes_4.py.snap new file mode 100644 index 0000000000000..abbbb06448be2 --- /dev/null +++ b/crates/ruff/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__typing-only-standard-library-import_runtime_evaluated_base_classes_4.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/flake8_type_checking/mod.rs +--- + diff --git a/crates/ruff/src/rules/flake8_unused_arguments/mod.rs b/crates/ruff/src/rules/flake8_unused_arguments/mod.rs index 4875916f5a5c8..b1faea753457a 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/mod.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/mod.rs @@ -1,5 +1,5 @@ //! Rules from [flake8-unused-arguments](https://pypi.org/project/flake8-unused-arguments/). -mod helpers; +pub(crate) mod helpers; pub(crate) mod rules; pub mod settings; diff --git a/crates/ruff/src/rules/flake8_unused_arguments/rules/unused_arguments.rs b/crates/ruff/src/rules/flake8_unused_arguments/rules/unused_arguments.rs index 0a7b06a051a81..986ab3599659c 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/rules/unused_arguments.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/rules/unused_arguments.rs @@ -2,7 +2,7 @@ use std::iter; use regex::Regex; use ruff_python_ast as ast; -use ruff_python_ast::{Arg, Arguments}; +use ruff_python_ast::{Parameter, Parameters, Ranged}; use ruff_diagnostics::DiagnosticKind; use ruff_diagnostics::{Diagnostic, Violation}; @@ -215,33 +215,33 @@ impl Argumentable { /// Check a plain function for unused arguments. fn function( argumentable: Argumentable, - args: &Arguments, - values: &Scope, + parameters: &Parameters, + scope: &Scope, semantic: &SemanticModel, dummy_variable_rgx: &Regex, ignore_variadic_names: bool, diagnostics: &mut Vec, ) { - let args = args + let args = parameters .posonlyargs .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) - .map(|arg_with_default| &arg_with_default.def) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .map(|parameter_with_default| ¶meter_with_default.parameter) .chain( - iter::once::>(args.vararg.as_deref()) + iter::once::>(parameters.vararg.as_deref()) .flatten() .skip(usize::from(ignore_variadic_names)), ) .chain( - iter::once::>(args.kwarg.as_deref()) + iter::once::>(parameters.kwarg.as_deref()) .flatten() .skip(usize::from(ignore_variadic_names)), ); call( argumentable, args, - values, + scope, semantic, dummy_variable_rgx, diagnostics, @@ -251,34 +251,34 @@ fn function( /// Check a method for unused arguments. fn method( argumentable: Argumentable, - args: &Arguments, - values: &Scope, + parameters: &Parameters, + scope: &Scope, semantic: &SemanticModel, dummy_variable_rgx: &Regex, ignore_variadic_names: bool, diagnostics: &mut Vec, ) { - let args = args + let args = parameters .posonlyargs .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) .skip(1) - .map(|arg_with_default| &arg_with_default.def) + .map(|parameter_with_default| ¶meter_with_default.parameter) .chain( - iter::once::>(args.vararg.as_deref()) + iter::once::>(parameters.vararg.as_deref()) .flatten() .skip(usize::from(ignore_variadic_names)), ) .chain( - iter::once::>(args.kwarg.as_deref()) + iter::once::>(parameters.kwarg.as_deref()) .flatten() .skip(usize::from(ignore_variadic_names)), ); call( argumentable, args, - values, + scope, semantic, dummy_variable_rgx, diagnostics, @@ -287,23 +287,23 @@ fn method( fn call<'a>( argumentable: Argumentable, - args: impl Iterator, - values: &Scope, + parameters: impl Iterator, + scope: &Scope, semantic: &SemanticModel, dummy_variable_rgx: &Regex, diagnostics: &mut Vec, ) { - diagnostics.extend(args.filter_map(|arg| { - let binding = values - .get(arg.arg.as_str()) + diagnostics.extend(parameters.filter_map(|arg| { + let binding = scope + .get(arg.name.as_str()) .map(|binding_id| semantic.binding(binding_id))?; if binding.kind.is_argument() && !binding.is_used() - && !dummy_variable_rgx.is_match(arg.arg.as_str()) + && !dummy_variable_rgx.is_match(arg.name.as_str()) { Some(Diagnostic::new( - argumentable.check_for(arg.arg.to_string()), - binding.range, + argumentable.check_for(arg.name.to_string()), + binding.range(), )) } else { None @@ -317,6 +317,10 @@ pub(crate) fn unused_arguments( scope: &Scope, diagnostics: &mut Vec, ) { + if scope.uses_locals() { + return; + } + let Some(parent) = &checker.semantic().first_non_type_parent_scope(scope) else { return; }; @@ -324,14 +328,7 @@ pub(crate) fn unused_arguments( match &scope.kind { ScopeKind::Function(ast::StmtFunctionDef { name, - args, - body, - decorator_list, - .. - }) - | ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef { - name, - args, + parameters, body, decorator_list, .. @@ -350,7 +347,7 @@ pub(crate) fn unused_arguments( { function( Argumentable::Function, - args, + parameters, scope, checker.semantic(), &checker.settings.dummy_variable_rgx, @@ -375,7 +372,7 @@ pub(crate) fn unused_arguments( { method( Argumentable::Method, - args, + parameters, scope, checker.semantic(), &checker.settings.dummy_variable_rgx, @@ -400,7 +397,7 @@ pub(crate) fn unused_arguments( { method( Argumentable::ClassMethod, - args, + parameters, scope, checker.semantic(), &checker.settings.dummy_variable_rgx, @@ -425,7 +422,7 @@ pub(crate) fn unused_arguments( { function( Argumentable::StaticMethod, - args, + parameters, scope, checker.semantic(), &checker.settings.dummy_variable_rgx, @@ -439,20 +436,22 @@ pub(crate) fn unused_arguments( } } } - ScopeKind::Lambda(ast::ExprLambda { args, .. }) => { - if checker.enabled(Argumentable::Lambda.rule_code()) { - function( - Argumentable::Lambda, - args, - scope, - checker.semantic(), - &checker.settings.dummy_variable_rgx, - checker - .settings - .flake8_unused_arguments - .ignore_variadic_names, - diagnostics, - ); + ScopeKind::Lambda(ast::ExprLambda { parameters, .. }) => { + if let Some(parameters) = parameters { + if checker.enabled(Argumentable::Lambda.rule_code()) { + function( + Argumentable::Lambda, + parameters, + scope, + checker.semantic(), + &checker.settings.dummy_variable_rgx, + checker + .settings + .flake8_unused_arguments + .ignore_variadic_names, + diagnostics, + ); + } } } _ => panic!("Expected ScopeKind::Function | ScopeKind::Lambda"), diff --git a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG002_ARG.py.snap b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG002_ARG.py.snap index 7c28c0eb5c182..bacd069607deb 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG002_ARG.py.snap +++ b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG002_ARG.py.snap @@ -1,40 +1,40 @@ --- source: crates/ruff/src/rules/flake8_unused_arguments/mod.rs --- -ARG.py:35:17: ARG002 Unused method argument: `x` +ARG.py:37:17: ARG002 Unused method argument: `x` | -33 | # Unused arguments. -34 | ### -35 | def f(self, x): +35 | # Unused arguments. +36 | ### +37 | def f(self, x): | ^ ARG002 -36 | print("Hello, world!") +38 | print("Hello, world!") | -ARG.py:38:20: ARG002 Unused method argument: `x` +ARG.py:40:20: ARG002 Unused method argument: `x` | -36 | print("Hello, world!") -37 | -38 | def f(self, /, x): +38 | print("Hello, world!") +39 | +40 | def f(self, /, x): | ^ ARG002 -39 | print("Hello, world!") +41 | print("Hello, world!") | -ARG.py:41:16: ARG002 Unused method argument: `x` +ARG.py:43:16: ARG002 Unused method argument: `x` | -39 | print("Hello, world!") -40 | -41 | def f(cls, x): +41 | print("Hello, world!") +42 | +43 | def f(cls, x): | ^ ARG002 -42 | print("Hello, world!") +44 | print("Hello, world!") | -ARG.py:190:24: ARG002 Unused method argument: `x` +ARG.py:192:24: ARG002 Unused method argument: `x` | -188 | ### -189 | class C: -190 | def __init__(self, x) -> None: +190 | ### +191 | class C: +192 | def __init__(self, x) -> None: | ^ ARG002 -191 | print("Hello, world!") +193 | print("Hello, world!") | diff --git a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG003_ARG.py.snap b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG003_ARG.py.snap index d029a11c43483..131b8c630355b 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG003_ARG.py.snap +++ b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG003_ARG.py.snap @@ -1,12 +1,12 @@ --- source: crates/ruff/src/rules/flake8_unused_arguments/mod.rs --- -ARG.py:45:16: ARG003 Unused class method argument: `x` +ARG.py:47:16: ARG003 Unused class method argument: `x` | -44 | @classmethod -45 | def f(cls, x): +46 | @classmethod +47 | def f(cls, x): | ^ ARG003 -46 | print("Hello, world!") +48 | print("Hello, world!") | diff --git a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG004_ARG.py.snap b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG004_ARG.py.snap index f6968b80074d9..0b28d1c4e3f56 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG004_ARG.py.snap +++ b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG004_ARG.py.snap @@ -1,28 +1,28 @@ --- source: crates/ruff/src/rules/flake8_unused_arguments/mod.rs --- -ARG.py:49:11: ARG004 Unused static method argument: `cls` +ARG.py:51:11: ARG004 Unused static method argument: `cls` | -48 | @staticmethod -49 | def f(cls, x): +50 | @staticmethod +51 | def f(cls, x): | ^^^ ARG004 -50 | print("Hello, world!") +52 | print("Hello, world!") | -ARG.py:49:16: ARG004 Unused static method argument: `x` +ARG.py:51:16: ARG004 Unused static method argument: `x` | -48 | @staticmethod -49 | def f(cls, x): +50 | @staticmethod +51 | def f(cls, x): | ^ ARG004 -50 | print("Hello, world!") +52 | print("Hello, world!") | -ARG.py:53:11: ARG004 Unused static method argument: `x` +ARG.py:55:11: ARG004 Unused static method argument: `x` | -52 | @staticmethod -53 | def f(x): +54 | @staticmethod +55 | def f(x): | ^ ARG004 -54 | print("Hello, world!") +56 | print("Hello, world!") | diff --git a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG005_ARG.py.snap b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG005_ARG.py.snap index aade2e18b8b3f..13c992c382ebb 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG005_ARG.py.snap +++ b/crates/ruff/src/rules/flake8_unused_arguments/snapshots/ruff__rules__flake8_unused_arguments__tests__ARG005_ARG.py.snap @@ -7,6 +7,8 @@ ARG.py:28:8: ARG005 Unused lambda argument: `x` 27 | ### 28 | lambda x: print("Hello, world!") | ^ ARG005 +29 | +30 | lambda: print("Hello, world!") | diff --git a/crates/ruff/src/rules/flake8_use_pathlib/rules/os_sep_split.rs b/crates/ruff/src/rules/flake8_use_pathlib/rules/os_sep_split.rs index f6176e1c263fc..e502b074e2241 100644 --- a/crates/ruff/src/rules/flake8_use_pathlib/rules/os_sep_split.rs +++ b/crates/ruff/src/rules/flake8_use_pathlib/rules/os_sep_split.rs @@ -1,7 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; -use ruff_python_ast::{Expr, ExprAttribute, Keyword, Ranged}; +use ruff_python_ast::{self as ast, Expr, ExprAttribute, Ranged}; use crate::checkers::ast::Checker; @@ -52,13 +51,8 @@ impl Violation for OsSepSplit { } /// PTH206 -pub(crate) fn os_sep_split( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { - let Expr::Attribute(ExprAttribute { attr, .. }) = func else { +pub(crate) fn os_sep_split(checker: &mut Checker, call: &ast::ExprCall) { + let Expr::Attribute(ExprAttribute { attr, .. }) = call.func.as_ref() else { return; }; @@ -66,28 +60,20 @@ pub(crate) fn os_sep_split( return; }; - let sep = if !args.is_empty() { - // `.split(os.sep)` - let [arg] = args else { - return; - }; - arg - } else if !keywords.is_empty() { - // `.split(sep=os.sep)` - let Some(keyword) = find_keyword(keywords, "sep") else { - return; - }; - &keyword.value - } else { + // Match `.split(os.sep)` or `.split(sep=os.sep)`, but avoid cases in which a `maxsplit` is + // specified. + if call.arguments.len() != 1 { + return; + } + + let Some(sep) = call.arguments.find_argument("sep", 0) else { return; }; if !checker .semantic() .resolve_call_path(sep) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["os", "sep"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["os", "sep"])) { return; } diff --git a/crates/ruff/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs b/crates/ruff/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs index 3cead2169d422..2a814c01a622a 100644 --- a/crates/ruff/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs +++ b/crates/ruff/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Constant, Expr, ExprCall, ExprConstant}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, ExprCall, ExprConstant}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; @@ -49,14 +49,16 @@ pub(crate) fn path_constructor_current_directory(checker: &mut Checker, expr: &E if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pathlib", "Path" | "PurePath"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pathlib", "Path" | "PurePath"])) { return; } - let Expr::Call(ExprCall { args, keywords, .. }) = expr else { + let Expr::Call(ExprCall { + arguments: Arguments { args, keywords, .. }, + .. + }) = expr + else { return; }; @@ -65,7 +67,7 @@ pub(crate) fn path_constructor_current_directory(checker: &mut Checker, expr: &E } let [Expr::Constant(ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), kind: _, range, })] = args.as_slice() diff --git a/crates/ruff/src/rules/flynt/helpers.rs b/crates/ruff/src/rules/flynt/helpers.rs index ff06b60645d76..35183bb020305 100644 --- a/crates/ruff/src/rules/flynt/helpers.rs +++ b/crates/ruff/src/rules/flynt/helpers.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, ConversionFlag, Expr}; +use ruff_python_ast::{self as ast, Arguments, Constant, ConversionFlag, Expr}; use ruff_text_size::TextRange; /// Wrap an expression in a `FormattedValue` with no special formatting. @@ -16,7 +16,7 @@ fn to_formatted_value_expr(inner: &Expr) -> Expr { /// Convert a string to a constant string expression. pub(super) fn to_constant_string(s: &str) -> Expr { let node = ast::ExprConstant { - value: Constant::Str(s.to_owned()), + value: s.to_owned().into(), kind: None, range: TextRange::default(), }; @@ -29,8 +29,12 @@ fn is_simple_call(expr: &Expr) -> bool { match expr { Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) => args.is_empty() && keywords.is_empty() && is_simple_callee(func), _ => false, @@ -48,14 +52,14 @@ fn is_simple_callee(func: &Expr) -> bool { } /// Convert an expression to a f-string element (if it looks like a good idea). -pub(super) fn to_fstring_elem(expr: &Expr) -> Option { +pub(super) fn to_f_string_element(expr: &Expr) -> Option { match expr { - // These are directly handled by `unparse_fstring_elem`: + // These are directly handled by `unparse_f_string_element`: Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. }) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::FormattedValue(_) => Some(expr.clone()), // These should be pretty safe to wrap in a formatted value. Expr::Constant(ast::ExprConstant { diff --git a/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs b/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs index 29cd1764d5a47..980680bb85b2b 100644 --- a/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs +++ b/crates/ruff/src/rules/flynt/rules/static_join_to_fstring.rs @@ -1,10 +1,11 @@ use itertools::Itertools; -use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; -use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Ranged}; +use ruff_text_size::TextRange; +use crate::autofix::snippet::SourceCodeSnippet; use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::flynt::helpers; @@ -29,19 +30,27 @@ use crate::rules::flynt::helpers; /// - [Python documentation: f-strings](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) #[violation] pub struct StaticJoinToFString { - expr: String, + expression: SourceCodeSnippet, } impl AlwaysAutofixableViolation for StaticJoinToFString { #[derive_message_formats] fn message(&self) -> String { - let StaticJoinToFString { expr } = self; - format!("Consider `{expr}` instead of string join") + let StaticJoinToFString { expression } = self; + if let Some(expression) = expression.full_display() { + format!("Consider `{expression}` instead of string join") + } else { + format!("Consider f-string instead of string join") + } } fn autofix_title(&self) -> String { - let StaticJoinToFString { expr } = self; - format!("Replace with `{expr}`") + let StaticJoinToFString { expression } = self; + if let Some(expression) = expression.full_display() { + format!("Replace with `{expression}`") + } else { + format!("Replace with f-string") + } } } @@ -61,22 +70,21 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { ) }) { let node = ast::ExprConstant { - value: Constant::Str( - joinees - .iter() - .filter_map(|expr| { - if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(string), - .. - }) = expr - { - Some(string.as_str()) - } else { - None - } - }) - .join(joiner), - ), + value: joinees + .iter() + .filter_map(|expr| { + if let Expr::Constant(ast::ExprConstant { + value: Constant::Str(ast::StringConstant { value, .. }), + .. + }) = expr + { + Some(value.as_str()) + } else { + None + } + }) + .join(joiner) + .into(), range: TextRange::default(), kind: None, }; @@ -87,7 +95,7 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { let mut first = true; for expr in joinees { - if expr.is_joined_str_expr() { + if expr.is_f_string_expr() { // Oops, already an f-string. We don't know how to handle those // gracefully right now. return None; @@ -95,29 +103,37 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option { if !std::mem::take(&mut first) { fstring_elems.push(helpers::to_constant_string(joiner)); } - fstring_elems.push(helpers::to_fstring_elem(expr)?); + fstring_elems.push(helpers::to_f_string_element(expr)?); } - let node = ast::ExprJoinedStr { + let node = ast::ExprFString { values: fstring_elems, + implicit_concatenated: false, range: TextRange::default(), }; Some(node.into()) } pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: &str) { - let Expr::Call(ast::ExprCall { args, keywords, .. }) = expr else { + let Expr::Call(ast::ExprCall { + arguments: Arguments { args, keywords, .. }, + .. + }) = expr + else { return; }; - if !keywords.is_empty() || args.len() != 1 { - // If there are kwargs or more than one argument, this is some non-standard - // string join call. + // If there are kwargs or more than one argument, this is some non-standard + // string join call. + if !keywords.is_empty() { return; } + let [arg] = args.as_slice() else { + return; + }; // Get the elements to join; skip (e.g.) generators, sets, etc. - let joinees = match &args[0] { + let joinees = match &arg { Expr::List(ast::ExprList { elts, .. }) if is_static_length(elts) => elts, Expr::Tuple(ast::ExprTuple { elts, .. }) if is_static_length(elts) => elts, _ => return, @@ -133,7 +149,7 @@ pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: let mut diagnostic = Diagnostic::new( StaticJoinToFString { - expr: contents.clone(), + expression: SourceCodeSnippet::new(contents.clone()), }, expr.range(), ); diff --git a/crates/ruff/src/rules/isort/annotate.rs b/crates/ruff/src/rules/isort/annotate.rs index 13e96286820fe..d434d0bde769f 100644 --- a/crates/ruff/src/rules/isort/annotate.rs +++ b/crates/ruff/src/rules/isort/annotate.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Ranged, Stmt}; +use ruff_python_ast::{self as ast, PySourceType, Ranged, Stmt}; use ruff_text_size::TextRange; use ruff_source_file::Locator; @@ -13,6 +13,7 @@ pub(crate) fn annotate_imports<'a>( comments: Vec>, locator: &Locator, split_on_trailing_comma: bool, + source_type: PySourceType, ) -> Vec> { let mut comments_iter = comments.into_iter().peekable(); @@ -71,7 +72,7 @@ pub(crate) fn annotate_imports<'a>( // import bar # noqa`). let mut inline = vec![]; if names.len() > 1 - || names.first().map_or(false, |alias| { + || names.first().is_some_and(|alias| { locator .contains_line_break(TextRange::new(import.start(), alias.start())) }) @@ -119,7 +120,7 @@ pub(crate) fn annotate_imports<'a>( names: aliases, level: level.map(|level| level.to_u32()), trailing_comma: if split_on_trailing_comma { - trailing_comma(import, locator) + trailing_comma(import, locator, source_type) } else { TrailingComma::default() }, diff --git a/crates/ruff/src/rules/isort/block.rs b/crates/ruff/src/rules/isort/block.rs index 8ee50b3ef1c7f..cc32b50a50e45 100644 --- a/crates/ruff/src/rules/isort/block.rs +++ b/crates/ruff/src/rules/isort/block.rs @@ -89,7 +89,7 @@ impl<'a> BlockBuilder<'a> { // sibling (i.e., as if the comment is the next statement, as // opposed to the class or function). match stmt { - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { + Stmt::FunctionDef(_) => { if helpers::has_comment_break(stmt, self.locator) { Trailer::Sibling } else { @@ -144,7 +144,7 @@ where while self .splits .peek() - .map_or(false, |split| stmt.start() >= **split) + .is_some_and(|split| stmt.start() >= **split) { self.splits.next(); } @@ -165,7 +165,7 @@ where // the case of multiple empty cells). while cell_offsets .peek() - .map_or(false, |split| stmt.start() >= **split) + .is_some_and(|split| stmt.start() >= **split) { cell_offsets.next(); } @@ -196,12 +196,6 @@ where } self.finalize(None); } - Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { - for stmt in body { - self.visit_stmt(stmt); - } - self.finalize(None); - } Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { for stmt in body { self.visit_stmt(stmt); @@ -219,17 +213,6 @@ where } self.finalize(None); } - Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { - for stmt in body { - self.visit_stmt(stmt); - } - self.finalize(None); - - for stmt in orelse { - self.visit_stmt(stmt); - } - self.finalize(None); - } Stmt::While(ast::StmtWhile { body, orelse, .. }) => { for stmt in body { self.visit_stmt(stmt); @@ -261,12 +244,6 @@ where } self.finalize(None); } - Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { - for stmt in body { - self.visit_stmt(stmt); - } - self.finalize(None); - } Stmt::Match(ast::StmtMatch { cases, .. }) => { for match_case in cases { self.visit_match_case(match_case); @@ -277,14 +254,7 @@ where handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { for except_handler in handlers { self.visit_except_handler(except_handler); diff --git a/crates/ruff/src/rules/isort/categorize.rs b/crates/ruff/src/rules/isort/categorize.rs index 3ed3d8d1a3ff4..d4b86a8e0f544 100644 --- a/crates/ruff/src/rules/isort/categorize.rs +++ b/crates/ruff/src/rules/isort/categorize.rs @@ -69,12 +69,13 @@ pub(crate) fn categorize<'a>( level: Option, src: &[PathBuf], package: Option<&Path>, + detect_same_package: bool, known_modules: &'a KnownModules, target_version: PythonVersion, ) -> &'a ImportSection { let module_base = module_name.split('.').next().unwrap(); let (import_type, reason) = { - if level.map_or(false, |level| level > 0) { + if level.is_some_and(|level| level > 0) { ( &ImportSection::Known(ImportType::LocalFolder), Reason::NonZeroLevel, @@ -88,7 +89,7 @@ pub(crate) fn categorize<'a>( &ImportSection::Known(ImportType::StandardLibrary), Reason::KnownStandardLibrary, ) - } else if same_package(package, module_base) { + } else if detect_same_package && same_package(package, module_base) { ( &ImportSection::Known(ImportType::FirstParty), Reason::SamePackage, @@ -113,7 +114,7 @@ pub(crate) fn categorize<'a>( } fn same_package(package: Option<&Path>, module_base: &str) -> bool { - package.map_or(false, |package| package.ends_with(module_base)) + package.is_some_and(|package| package.ends_with(module_base)) } fn match_sources<'a>(paths: &'a [PathBuf], base: &str) -> Option<&'a Path> { @@ -137,6 +138,7 @@ pub(crate) fn categorize_imports<'a>( block: ImportBlock<'a>, src: &[PathBuf], package: Option<&Path>, + detect_same_package: bool, known_modules: &'a KnownModules, target_version: PythonVersion, ) -> BTreeMap<&'a ImportSection, ImportBlock<'a>> { @@ -148,6 +150,7 @@ pub(crate) fn categorize_imports<'a>( None, src, package, + detect_same_package, known_modules, target_version, ); @@ -164,6 +167,7 @@ pub(crate) fn categorize_imports<'a>( import_from.level, src, package, + detect_same_package, known_modules, target_version, ); @@ -180,6 +184,7 @@ pub(crate) fn categorize_imports<'a>( import_from.level, src, package, + detect_same_package, known_modules, target_version, ); @@ -196,6 +201,7 @@ pub(crate) fn categorize_imports<'a>( import_from.level, src, package, + detect_same_package, known_modules, target_version, ); diff --git a/crates/ruff/src/rules/isort/comments.rs b/crates/ruff/src/rules/isort/comments.rs index b7963ff1ab244..b492ce6309cc4 100644 --- a/crates/ruff/src/rules/isort/comments.rs +++ b/crates/ruff/src/rules/isort/comments.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::{TextRange, TextSize}; - +use ruff_python_ast::Ranged; +use ruff_python_index::Indexer; use ruff_source_file::Locator; +use ruff_text_size::TextRange; #[derive(Debug)] pub(crate) struct Comment<'a> { @@ -11,30 +11,25 @@ pub(crate) struct Comment<'a> { pub(crate) range: TextRange, } -impl Comment<'_> { - pub(crate) const fn start(&self) -> TextSize { - self.range.start() - } - - pub(crate) const fn end(&self) -> TextSize { - self.range.end() +impl Ranged for Comment<'_> { + fn range(&self) -> TextRange { + self.range } } /// Collect all comments in an import block. -pub(crate) fn collect_comments<'a>(range: TextRange, locator: &'a Locator) -> Vec> { - let contents = locator.slice(range); - lexer::lex_starts_at(contents, Mode::Module, range.start()) - .flatten() - .filter_map(|(tok, range)| { - if let Tok::Comment(value) = tok { - Some(Comment { - value: value.into(), - range, - }) - } else { - None - } +pub(crate) fn collect_comments<'a>( + range: TextRange, + locator: &'a Locator, + indexer: &'a Indexer, +) -> Vec> { + indexer + .comment_ranges() + .comments_in_range(range) + .iter() + .map(|range| Comment { + value: locator.slice(*range).into(), + range: *range, }) .collect() } diff --git a/crates/ruff/src/rules/isort/helpers.rs b/crates/ruff/src/rules/isort/helpers.rs index adf185891db5d..00f9504ac3212 100644 --- a/crates/ruff/src/rules/isort/helpers.rs +++ b/crates/ruff/src/rules/isort/helpers.rs @@ -1,5 +1,5 @@ -use ruff_python_ast::{Ranged, Stmt}; -use ruff_python_parser::{lexer, Mode, Tok}; +use ruff_python_ast::{PySourceType, Ranged, Stmt}; +use ruff_python_parser::{lexer, AsMode, Tok}; use ruff_python_trivia::PythonWhitespace; use ruff_source_file::{Locator, UniversalNewlines}; @@ -8,11 +8,15 @@ use crate::rules::isort::types::TrailingComma; /// Return `true` if a `Stmt::ImportFrom` statement ends with a magic /// trailing comma. -pub(super) fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma { +pub(super) fn trailing_comma( + stmt: &Stmt, + locator: &Locator, + source_type: PySourceType, +) -> TrailingComma { let contents = locator.slice(stmt.range()); let mut count = 0u32; let mut trailing_comma = TrailingComma::Absent; - for (tok, _) in lexer::lex_starts_at(contents, Mode::Module, stmt.start()).flatten() { + for (tok, _) in lexer::lex_starts_at(contents, source_type.as_mode(), stmt.start()).flatten() { if matches!(tok, Tok::Lpar) { count = count.saturating_add(1); } diff --git a/crates/ruff/src/rules/isort/mod.rs b/crates/ruff/src/rules/isort/mod.rs index 854b26728b386..074f59be1530e 100644 --- a/crates/ruff/src/rules/isort/mod.rs +++ b/crates/ruff/src/rules/isort/mod.rs @@ -11,6 +11,7 @@ pub use categorize::{ImportSection, ImportType}; use comments::Comment; use normalize::normalize_imports; use order::order_imports; +use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; use ruff_source_file::Locator; use settings::RelativeImportsOrder; @@ -72,6 +73,7 @@ pub(crate) fn format_imports( stylist: &Stylist, src: &[PathBuf], package: Option<&Path>, + source_type: PySourceType, combine_as_imports: bool, force_single_line: bool, force_sort_within_sections: bool, @@ -80,6 +82,7 @@ pub(crate) fn format_imports( force_to_top: &BTreeSet, known_modules: &KnownModules, order_by_type: bool, + detect_same_package: bool, relative_imports_order: RelativeImportsOrder, single_line_exclusions: &BTreeSet, split_on_trailing_comma: bool, @@ -94,7 +97,13 @@ pub(crate) fn format_imports( section_order: &[ImportSection], ) -> String { let trailer = &block.trailer; - let block = annotate_imports(&block.imports, comments, locator, split_on_trailing_comma); + let block = annotate_imports( + &block.imports, + comments, + locator, + split_on_trailing_comma, + source_type, + ); // Normalize imports (i.e., deduplicate, aggregate `from` imports). let block = normalize_imports( @@ -121,6 +130,7 @@ pub(crate) fn format_imports( force_to_top, known_modules, order_by_type, + detect_same_package, relative_imports_order, split_on_trailing_comma, classes, @@ -179,6 +189,7 @@ fn format_import_block( force_to_top: &BTreeSet, known_modules: &KnownModules, order_by_type: bool, + detect_same_package: bool, relative_imports_order: RelativeImportsOrder, split_on_trailing_comma: bool, classes: &BTreeSet, @@ -190,7 +201,14 @@ fn format_import_block( section_order: &[ImportSection], ) -> String { // Categorize by type (e.g., first-party vs. third-party). - let mut block_by_type = categorize_imports(block, src, package, known_modules, target_version); + let mut block_by_type = categorize_imports( + block, + src, + package, + detect_same_package, + known_modules, + target_version, + ); let mut output = String::new(); @@ -754,6 +772,7 @@ mod tests { } #[test_case(Path::new("comment.py"))] + #[test_case(Path::new("comments_and_newlines.py"))] #[test_case(Path::new("docstring.py"))] #[test_case(Path::new("docstring.pyi"))] #[test_case(Path::new("docstring_only.py"))] @@ -783,6 +802,7 @@ mod tests { } #[test_case(Path::new("comment.py"))] + #[test_case(Path::new("comments_and_newlines.py"))] #[test_case(Path::new("docstring.py"))] #[test_case(Path::new("docstring.pyi"))] #[test_case(Path::new("docstring_only.py"))] @@ -1074,4 +1094,38 @@ mod tests { assert_messages!(snapshot, diagnostics); Ok(()) } + + #[test] + fn detect_same_package() -> Result<()> { + let diagnostics = test_path( + Path::new("isort/detect_same_package/foo/bar.py"), + &Settings { + src: vec![], + isort: super::settings::Settings { + detect_same_package: true, + ..super::settings::Settings::default() + }, + ..Settings::for_rule(Rule::UnsortedImports) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } + + #[test] + fn no_detect_same_package() -> Result<()> { + let diagnostics = test_path( + Path::new("isort/detect_same_package/foo/bar.py"), + &Settings { + src: vec![], + isort: super::settings::Settings { + detect_same_package: false, + ..super::settings::Settings::default() + }, + ..Settings::for_rule(Rule::UnsortedImports) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } } diff --git a/crates/ruff/src/rules/isort/normalize.rs b/crates/ruff/src/rules/isort/normalize.rs index 1c0e4312edfdd..ceee1cb4a35f1 100644 --- a/crates/ruff/src/rules/isort/normalize.rs +++ b/crates/ruff/src/rules/isort/normalize.rs @@ -58,7 +58,7 @@ pub(crate) fn normalize_imports<'a>( // Whether to track each member of the import as a separate entry. let isolate_aliases = force_single_line && module.map_or(true, |module| !single_line_exclusions.contains(module)) - && !names.first().map_or(false, |alias| alias.name == "*"); + && !names.first().is_some_and(|alias| alias.name == "*"); // Insert comments on the statement itself. if isolate_aliases { diff --git a/crates/ruff/src/rules/isort/rules/add_required_imports.rs b/crates/ruff/src/rules/isort/rules/add_required_imports.rs index 9bcdc477e4342..dd71b1e552638 100644 --- a/crates/ruff/src/rules/isort/rules/add_required_imports.rs +++ b/crates/ruff/src/rules/isort/rules/add_required_imports.rs @@ -1,6 +1,5 @@ use log::error; -use ruff_python_ast::{self as ast, Stmt, Suite}; -use ruff_python_parser::Parse; +use ruff_python_ast::{self as ast, PySourceType, Stmt, Suite}; use ruff_text_size::{TextRange, TextSize}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; @@ -8,6 +7,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::is_docstring_stmt; use ruff_python_ast::imports::{Alias, AnyImport, FutureImport, Import, ImportFrom}; use ruff_python_codegen::Stylist; +use ruff_python_parser::parse_suite; use ruff_source_file::Locator; use crate::importer::Importer; @@ -91,7 +91,7 @@ fn add_required_import( locator: &Locator, stylist: &Stylist, settings: &Settings, - is_stub: bool, + source_type: PySourceType, ) -> Option { // Don't add imports to semantically-empty files. if python_ast.iter().all(is_docstring_stmt) { @@ -99,7 +99,7 @@ fn add_required_import( } // We don't need to add `__future__` imports to stubs. - if is_stub && required_import.is_future_import() { + if source_type.is_stub() && required_import.is_future_import() { return None; } @@ -131,14 +131,14 @@ pub(crate) fn add_required_imports( locator: &Locator, stylist: &Stylist, settings: &Settings, - is_stub: bool, + source_type: PySourceType, ) -> Vec { settings .isort .required_imports .iter() .flat_map(|required_import| { - let Ok(body) = Suite::parse(required_import, "") else { + let Ok(body) = parse_suite(required_import, "") else { error!("Failed to parse required import: `{}`", required_import); return vec![]; }; @@ -172,7 +172,7 @@ pub(crate) fn add_required_imports( locator, stylist, settings, - is_stub, + source_type, ) }) .collect(), @@ -190,7 +190,7 @@ pub(crate) fn add_required_imports( locator, stylist, settings, - is_stub, + source_type, ) }) .collect(), diff --git a/crates/ruff/src/rules/isort/rules/organize_imports.rs b/crates/ruff/src/rules/isort/rules/organize_imports.rs index 02873311d91cf..3681ba1af61ff 100644 --- a/crates/ruff/src/rules/isort/rules/organize_imports.rs +++ b/crates/ruff/src/rules/isort/rules/organize_imports.rs @@ -1,16 +1,16 @@ use std::path::Path; use itertools::{EitherOrBoth, Itertools}; -use ruff_python_ast::{Ranged, Stmt}; -use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::whitespace::{followed_by_multi_statement_line, trailing_lines_end}; +use ruff_python_ast::whitespace::trailing_lines_end; +use ruff_python_ast::{PySourceType, Ranged, Stmt}; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; use ruff_python_trivia::{leading_indentation, textwrap::indent, PythonWhitespace}; use ruff_source_file::{Locator, UniversalNewlines}; +use ruff_text_size::TextRange; use crate::line_width::LineWidth; use crate::registry::AsRule; @@ -87,6 +87,7 @@ pub(crate) fn organize_imports( indexer: &Indexer, settings: &Settings, package: Option<&Path>, + source_type: PySourceType, ) -> Option { let indentation = locator.slice(extract_indentation_range(&block.imports, locator)); let indentation = leading_indentation(indentation); @@ -96,7 +97,7 @@ pub(crate) fn organize_imports( // Special-cases: there's leading or trailing content in the import block. These // are too hard to get right, and relatively rare, so flag but don't fix. if indexer.preceded_by_multi_statement_line(block.imports.first().unwrap(), locator) - || followed_by_multi_statement_line(block.imports.last().unwrap(), locator) + || indexer.followed_by_multi_statement_line(block.imports.last().unwrap(), locator) { return Some(Diagnostic::new(UnsortedImports, range)); } @@ -105,6 +106,7 @@ pub(crate) fn organize_imports( let comments = comments::collect_comments( TextRange::new(range.start(), locator.full_line_end(range.end())), locator, + indexer, ); let trailing_line_end = if block.trailer.is_none() { @@ -123,6 +125,7 @@ pub(crate) fn organize_imports( stylist, &settings.src, package, + source_type, settings.isort.combine_as_imports, settings.isort.force_single_line, settings.isort.force_sort_within_sections, @@ -131,6 +134,7 @@ pub(crate) fn organize_imports( &settings.isort.force_to_top, &settings.isort.known_modules, settings.isort.order_by_type, + settings.isort.detect_same_package, settings.isort.relative_imports_order, &settings.isort.single_line_exclusions, settings.isort.split_on_trailing_comma, diff --git a/crates/ruff/src/rules/isort/settings.rs b/crates/ruff/src/rules/isort/settings.rs index 8e9648df1bba2..310fcd74e48f8 100644 --- a/crates/ruff/src/rules/isort/settings.rs +++ b/crates/ruff/src/rules/isort/settings.rs @@ -305,6 +305,21 @@ pub struct Options { )] /// Override in which order the sections should be output. Can be used to move custom sections. pub section_order: Option>, + #[option( + default = r#"true"#, + value_type = "bool", + example = r#" + detect-same-package = false + "# + )] + /// Whether to automatically mark imports from within the same package as first-party. + /// For example, when `detect-same-package = true`, then when analyzing files within the + /// `foo` package, any imports from within the `foo` package will be considered first-party. + /// + /// This heuristic is often unnecessary when `src` is configured to detect all first-party + /// sources; however, if `src` is _not_ configured, this heuristic can be useful to detect + /// first-party imports from _within_ (but not _across_) first-party packages. + pub detect_same_package: Option, // Tables are required to go last. #[option( default = "{}", @@ -331,6 +346,7 @@ pub struct Settings { pub force_wrap_aliases: bool, pub force_to_top: BTreeSet, pub known_modules: KnownModules, + pub detect_same_package: bool, pub order_by_type: bool, pub relative_imports_order: RelativeImportsOrder, pub single_line_exclusions: BTreeSet, @@ -352,6 +368,7 @@ impl Default for Settings { combine_as_imports: false, force_single_line: false, force_sort_within_sections: false, + detect_same_package: true, case_sensitive: false, force_wrap_aliases: false, force_to_top: BTreeSet::new(), @@ -509,6 +526,7 @@ impl TryFrom for Settings { force_sort_within_sections: options.force_sort_within_sections.unwrap_or(false), case_sensitive: options.case_sensitive.unwrap_or(false), force_wrap_aliases: options.force_wrap_aliases.unwrap_or(false), + detect_same_package: options.detect_same_package.unwrap_or(true), force_to_top: BTreeSet::from_iter(options.force_to_top.unwrap_or_default()), known_modules: KnownModules::new( known_first_party, @@ -595,6 +613,7 @@ impl From for Options { force_sort_within_sections: Some(settings.force_sort_within_sections), case_sensitive: Some(settings.case_sensitive), force_wrap_aliases: Some(settings.force_wrap_aliases), + detect_same_package: Some(settings.detect_same_package), force_to_top: Some(settings.force_to_top.into_iter().collect()), known_first_party: Some( settings diff --git a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__detect_same_package.snap b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__detect_same_package.snap new file mode 100644 index 0000000000000..4b75e7ede697a --- /dev/null +++ b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__detect_same_package.snap @@ -0,0 +1,19 @@ +--- +source: crates/ruff/src/rules/isort/mod.rs +--- +bar.py:1:1: I001 [*] Import block is un-sorted or un-formatted + | +1 | / import os +2 | | import pandas +3 | | import foo.baz + | + = help: Organize imports + +ℹ Fix +1 1 | import os + 2 |+ +2 3 | import pandas + 4 |+ +3 5 | import foo.baz + + diff --git a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__if_elif_else.py.snap b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__if_elif_else.py.snap index 514bc775e9c92..4a9a844881c5a 100644 --- a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__if_elif_else.py.snap +++ b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__if_elif_else.py.snap @@ -14,9 +14,8 @@ if_elif_else.py:6:1: I001 [*] Import block is un-sorted or un-formatted 3 3 | elif "setuptools" in sys.modules: 4 4 | from setuptools.command.sdist import sdist as _sdist 5 5 | else: -6 |- from setuptools.command.sdist import sdist as _sdist -7 6 | from distutils.command.sdist import sdist as _sdist - 7 |+ - 8 |+ from setuptools.command.sdist import sdist as _sdist + 6 |+ from distutils.command.sdist import sdist as _sdist +6 7 | from setuptools.command.sdist import sdist as _sdist +7 |- from distutils.command.sdist import sdist as _sdist diff --git a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__no_detect_same_package.snap b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__no_detect_same_package.snap new file mode 100644 index 0000000000000..2036ce6762b82 --- /dev/null +++ b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__no_detect_same_package.snap @@ -0,0 +1,19 @@ +--- +source: crates/ruff/src/rules/isort/mod.rs +--- +bar.py:1:1: I001 [*] Import block is un-sorted or un-formatted + | +1 | / import os +2 | | import pandas +3 | | import foo.baz + | + = help: Organize imports + +ℹ Fix +1 1 | import os +2 |-import pandas + 2 |+ +3 3 | import foo.baz + 4 |+import pandas + + diff --git a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_comments_and_newlines.py.snap b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_comments_and_newlines.py.snap new file mode 100644 index 0000000000000..107c3ef147d64 --- /dev/null +++ b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_comments_and_newlines.py.snap @@ -0,0 +1,20 @@ +--- +source: crates/ruff/src/rules/isort/mod.rs +--- +comments_and_newlines.py:1:1: I002 [*] Missing required import: `from __future__ import annotations` + | +1 | #!/usr/bin/env python3 + | I002 +2 | # A copyright notice could go here + | + = help: Insert required import: `from future import annotations` + +ℹ Fix +2 2 | # A copyright notice could go here +3 3 | +4 4 | # A linter directive could go here + 5 |+from __future__ import annotations +5 6 | +6 7 | x = 1 + + diff --git a/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_with_alias_comments_and_newlines.py.snap b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_with_alias_comments_and_newlines.py.snap new file mode 100644 index 0000000000000..a9ea7adf2e3bd --- /dev/null +++ b/crates/ruff/src/rules/isort/snapshots/ruff__rules__isort__tests__required_import_with_alias_comments_and_newlines.py.snap @@ -0,0 +1,20 @@ +--- +source: crates/ruff/src/rules/isort/mod.rs +--- +comments_and_newlines.py:1:1: I002 [*] Missing required import: `from __future__ import annotations as _annotations` + | +1 | #!/usr/bin/env python3 + | I002 +2 | # A copyright notice could go here + | + = help: Insert required import: `from future import annotations as _annotations` + +ℹ Fix +2 2 | # A copyright notice could go here +3 3 | +4 4 | # A linter directive could go here + 5 |+from __future__ import annotations as _annotations +5 6 | +6 7 | x = 1 + + diff --git a/crates/ruff/src/rules/isort/sorting.rs b/crates/ruff/src/rules/isort/sorting.rs index 75bb9a265329b..444e550406d0d 100644 --- a/crates/ruff/src/rules/isort/sorting.rs +++ b/crates/ruff/src/rules/isort/sorting.rs @@ -35,7 +35,7 @@ fn prefix( } else if name.len() > 1 && str::is_cased_uppercase(name) { // Ex) `CONSTANT` Prefix::Constants - } else if name.chars().next().map_or(false, char::is_uppercase) { + } else if name.chars().next().is_some_and(char::is_uppercase) { // Ex) `Class` Prefix::Classes } else { diff --git a/crates/ruff/src/rules/mccabe/rules/function_is_too_complex.rs b/crates/ruff/src/rules/mccabe/rules/function_is_too_complex.rs index 4bd40416487ca..c56ae7e2ed4ab 100644 --- a/crates/ruff/src/rules/mccabe/rules/function_is_too_complex.rs +++ b/crates/ruff/src/rules/mccabe/rules/function_is_too_complex.rs @@ -82,14 +82,12 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize { complexity += get_complexity_number(&clause.body); } } - Stmt::For(ast::StmtFor { body, orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) => { complexity += 1; complexity += get_complexity_number(body); complexity += get_complexity_number(orelse); } - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::With(ast::StmtWith { body, .. }) => { complexity += get_complexity_number(body); } Stmt::While(ast::StmtWhile { body, orelse, .. }) => { @@ -108,14 +106,7 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize { handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { complexity += get_complexity_number(body); if !orelse.is_empty() { @@ -131,8 +122,7 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize { complexity += get_complexity_number(body); } } - Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { + Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => { complexity += 1; complexity += get_complexity_number(body); } @@ -169,8 +159,8 @@ pub(crate) fn function_is_too_complex( #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::Suite; - use ruff_python_parser::Parse; + + use ruff_python_parser::parse_suite; use super::get_complexity_number; @@ -180,7 +170,7 @@ mod tests { def trivial(): pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -191,7 +181,7 @@ def trivial(): def expr_as_statement(): 0xF00D "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -204,7 +194,7 @@ def sequential(n): s = k + n return s "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -220,7 +210,7 @@ def if_elif_else_dead_path(n): else: return "smaller than or equal to three" "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 3); Ok(()) } @@ -237,7 +227,7 @@ def nested_ifs(): else: return "smaller than or equal to three" "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 3); Ok(()) } @@ -249,7 +239,7 @@ def for_loop(): for i in range(10): print(i) "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 2); Ok(()) } @@ -263,7 +253,7 @@ def for_else(mylist): else: print(None) "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 2); Ok(()) } @@ -277,7 +267,7 @@ def recursive(n): else: return n "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 2); Ok(()) } @@ -294,7 +284,7 @@ def nested_functions(): a() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 3); Ok(()) } @@ -312,7 +302,7 @@ def try_else(): else: print(4) "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 4); Ok(()) } @@ -329,7 +319,7 @@ def nested_try_finally(): finally: print(3) "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -346,7 +336,7 @@ async def foobar(a, b, c): async for x in a: pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 3); Ok(()) } @@ -357,7 +347,7 @@ async def foobar(a, b, c): def annotated_assign(): x: Any = None "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -393,7 +383,7 @@ class Class: return ServiceProvider(Logger()) "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 9); Ok(()) } @@ -407,7 +397,7 @@ def process_detect_lines(): finally: pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 1); Ok(()) } @@ -422,7 +412,7 @@ def process_detect_lines(): if res: errors.append(f"Non-zero exit code {res}") "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 2); Ok(()) } @@ -435,7 +425,7 @@ def with_lock(): if foo: print('bar') "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(get_complexity_number(&stmts), 2); Ok(()) } diff --git a/crates/ruff/src/rules/pandas_vet/helpers.rs b/crates/ruff/src/rules/pandas_vet/helpers.rs index 9da577d606912..c0952f61afcdb 100644 --- a/crates/ruff/src/rules/pandas_vet/helpers.rs +++ b/crates/ruff/src/rules/pandas_vet/helpers.rs @@ -1,8 +1,7 @@ -use ruff_python_ast as ast; use ruff_python_ast::Expr; +use ruff_python_semantic::{BindingKind, Imported, SemanticModel}; -use ruff_python_semantic::{BindingKind, Import, SemanticModel}; - +#[derive(Debug)] pub(super) enum Resolution { /// The expression resolves to an irrelevant expression type (e.g., a constant). IrrelevantExpression, @@ -26,22 +25,29 @@ pub(super) fn test_expression(expr: &Expr, semantic: &SemanticModel) -> Resoluti | Expr::ListComp(_) | Expr::DictComp(_) | Expr::GeneratorExp(_) => Resolution::IrrelevantExpression, - Expr::Name(ast::ExprName { id, .. }) => { + Expr::Name(name) => { semantic - .find_binding(id) - .map_or(Resolution::IrrelevantBinding, |binding| { - match binding.kind { + .resolve_name(name) + .map_or(Resolution::IrrelevantBinding, |id| { + match &semantic.binding(id).kind { + BindingKind::Argument => { + // Avoid, e.g., `self.values`. + if matches!(name.id.as_str(), "self" | "cls") { + Resolution::IrrelevantBinding + } else { + Resolution::RelevantLocal + } + } BindingKind::Annotation - | BindingKind::Argument | BindingKind::Assignment | BindingKind::NamedExprAssignment | BindingKind::UnpackedAssignment | BindingKind::LoopVar | BindingKind::Global | BindingKind::Nonlocal(_) => Resolution::RelevantLocal, - BindingKind::Import(Import { - qualified_name: module, - }) if module == "pandas" => Resolution::PandasModule, + BindingKind::Import(import) if matches!(import.call_path(), ["pandas"]) => { + Resolution::PandasModule + } _ => Resolution::IrrelevantBinding, } }) diff --git a/crates/ruff/src/rules/pandas_vet/mod.rs b/crates/ruff/src/rules/pandas_vet/mod.rs index b57f0836dfe6f..b2c2d150fe33f 100644 --- a/crates/ruff/src/rules/pandas_vet/mod.rs +++ b/crates/ruff/src/rules/pandas_vet/mod.rs @@ -209,6 +209,23 @@ mod tests { "#, "PD011_pass_values_call" )] + #[test_case( + r#" + import pandas as pd + x = pd.DataFrame() + x.values = 1 + "#, + "PD011_pass_values_store" + )] + #[test_case( + r#" + class Class: + def __init__(self, values: str) -> None: + self.values = values + print(self.values) + "#, + "PD011_pass_values_instance" + )] #[test_case( r#" import pandas as pd diff --git a/crates/ruff/src/rules/pandas_vet/rules/attr.rs b/crates/ruff/src/rules/pandas_vet/rules/attr.rs index de8981c63d8d6..05f3505db79a8 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/attr.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/attr.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Expr, Ranged}; +use ruff_python_ast::{self as ast, Expr, ExprContext, Ranged}; use ruff_diagnostics::Violation; use ruff_diagnostics::{Diagnostic, DiagnosticKind}; @@ -44,8 +44,14 @@ impl Violation for PandasUseOfDotValues { } } -pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: &Expr) { - let violation: DiagnosticKind = match attr { +pub(crate) fn attr(checker: &mut Checker, attribute: &ast::ExprAttribute) { + // Avoid, e.g., `x.values = y`. + if matches!(attribute.ctx, ExprContext::Store | ExprContext::Del) { + return; + } + + let violation: DiagnosticKind = match attribute.attr.as_str() { + // PD011 "values" if checker.settings.rules.enabled(Rule::PandasUseOfDotValues) => { PandasUseOfDotValues.into() } @@ -53,7 +59,7 @@ pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: & }; // Avoid flagging on function calls (e.g., `df.values()`). - if let Some(parent) = checker.semantic().expr_parent() { + if let Some(parent) = checker.semantic().current_expression_parent() { if matches!(parent, Expr::Call(_)) { return; } @@ -62,7 +68,7 @@ pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: & // Avoid flagging on non-DataFrames (e.g., `{"a": 1}.values`), and on irrelevant bindings // (like imports). if !matches!( - test_expression(value, checker.semantic()), + test_expression(attribute.value.as_ref(), checker.semantic()), Resolution::RelevantLocal ) { return; @@ -70,5 +76,5 @@ pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: & checker .diagnostics - .push(Diagnostic::new(violation, attr_expr.range())); + .push(Diagnostic::new(violation, attribute.range())); } diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index 543c9cc2f2a87..cecd169ad0eb0 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -1,13 +1,10 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::is_const_true; -use ruff_python_semantic::{BindingKind, Import}; +use ruff_python_ast::{self as ast, Keyword, Ranged}; use ruff_source_file::Locator; -use crate::autofix::edits::remove_argument; +use crate::autofix::edits::{remove_argument, Parentheses}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -52,33 +49,18 @@ impl Violation for PandasUseOfInplaceArgument { } /// PD002 -pub(crate) fn inplace_argument( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn inplace_argument(checker: &mut Checker, call: &ast::ExprCall) { // If the function was imported from another module, and it's _not_ Pandas, abort. - if let Some(call_path) = checker.semantic().resolve_call_path(func) { - if !call_path - .first() - .and_then(|module| checker.semantic().find_binding(module)) - .map_or(false, |binding| { - matches!( - binding.kind, - BindingKind::Import(Import { - qualified_name: "pandas" - }) - ) - }) - { - return; - } + if checker + .semantic() + .resolve_call_path(&call.func) + .is_some_and(|call_path| !matches!(call_path.as_slice(), ["pandas", ..])) + { + return; } let mut seen_star = false; - for keyword in keywords.iter().rev() { + for keyword in call.arguments.keywords.iter().rev() { let Some(arg) = &keyword.arg else { seen_star = true; continue; @@ -92,22 +74,13 @@ pub(crate) fn inplace_argument( // the star argument _doesn't_ contain an override). // 2. The call is part of a larger expression (we're converting an expression to a // statement, and expressions can't contain statements). - // 3. The call is in a lambda (we can't assign to a variable in a lambda). This - // should be unnecessary, as lambdas are expressions, and so (2) should apply, - // but we don't currently restore expression stacks when parsing deferred nodes, - // and so the parent is lost. if !seen_star - && checker.semantic().stmt().is_expr_stmt() - && checker.semantic().expr_parent().is_none() - && !checker.semantic().scope().kind.is_lambda() + && checker.semantic().current_statement().is_expr_stmt() + && checker.semantic().current_expression_parent().is_none() { - if let Some(fix) = convert_inplace_argument_to_assignment( - checker.locator(), - expr, - keyword.range(), - args, - keywords, - ) { + if let Some(fix) = + convert_inplace_argument_to_assignment(call, keyword, checker.locator()) + { diagnostic.set_fix(fix); } } @@ -125,23 +98,25 @@ pub(crate) fn inplace_argument( /// Remove the `inplace` argument from a function call and replace it with an /// assignment. fn convert_inplace_argument_to_assignment( + call: &ast::ExprCall, + keyword: &Keyword, locator: &Locator, - expr: &Expr, - expr_range: TextRange, - args: &[Expr], - keywords: &[Keyword], ) -> Option { // Add the assignment. - let call = expr.as_call_expr()?; let attr = call.func.as_attribute_expr()?; let insert_assignment = Edit::insertion( format!("{name} = ", name = locator.slice(attr.value.range())), - expr.start(), + call.start(), ); // Remove the `inplace` argument. - let remove_argument = - remove_argument(locator, call.func.end(), expr_range, args, keywords, false).ok()?; + let remove_argument = remove_argument( + keyword, + &call.arguments, + Parentheses::Preserve, + locator.contents(), + ) + .ok()?; Some(Fix::suggested_edits(insert_assignment, [remove_argument])) } diff --git a/crates/ruff/src/rules/pandas_vet/rules/read_table.rs b/crates/ruff/src/rules/pandas_vet/rules/read_table.rs index 48f49fa287b61..fb03d56ef29ec 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/read_table.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/read_table.rs @@ -1,9 +1,7 @@ -use ruff_python_ast as ast; -use ruff_python_ast::{Constant, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast as ast; +use ruff_python_ast::{Constant, Expr, Ranged}; use crate::checkers::ast::Checker; @@ -46,23 +44,24 @@ impl Violation for PandasUseOfDotReadTable { } /// PD012 -pub(crate) fn use_of_read_table(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { +pub(crate) fn use_of_read_table(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["pandas", "read_table"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["pandas", "read_table"])) { if let Some(Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. - })) = find_keyword(keywords, "sep").map(|keyword| &keyword.value) + })) = call + .arguments + .find_keyword("sep") + .map(|keyword| &keyword.value) { - if value.as_str() == "," { + if value == "," { checker .diagnostics - .push(Diagnostic::new(PandasUseOfDotReadTable, func.range())); + .push(Diagnostic::new(PandasUseOfDotReadTable, call.func.range())); } } } diff --git a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_instance.snap b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_instance.snap new file mode 100644 index 0000000000000..cee5b2f842656 --- /dev/null +++ b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_instance.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pandas_vet/mod.rs +--- + diff --git a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_store.snap b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_store.snap new file mode 100644 index 0000000000000..cee5b2f842656 --- /dev/null +++ b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD011_pass_values_store.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pandas_vet/mod.rs +--- + diff --git a/crates/ruff/src/rules/pep8_naming/helpers.rs b/crates/ruff/src/rules/pep8_naming/helpers.rs index 94564c48ab505..ac23f6c511fe9 100644 --- a/crates/ruff/src/rules/pep8_naming/helpers.rs +++ b/crates/ruff/src/rules/pep8_naming/helpers.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Stmt}; use ruff_python_semantic::SemanticModel; use ruff_python_stdlib::str::{is_cased_lowercase, is_cased_uppercase}; @@ -29,7 +29,7 @@ pub(super) fn is_named_tuple_assignment(stmt: &Stmt, semantic: &SemanticModel) - let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { + semantic.resolve_call_path(func).is_some_and(|call_path| { matches!( call_path.as_slice(), ["collections", "namedtuple"] | ["typing", "NamedTuple"] @@ -44,9 +44,9 @@ pub(super) fn is_typed_dict_assignment(stmt: &Stmt, semantic: &SemanticModel) -> let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["typing", "TypedDict"]) - }) + semantic + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "TypedDict"])) } pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool { @@ -56,15 +56,18 @@ pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> b let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else { return false; }; - semantic.resolve_call_path(func).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["typing", "TypeVar" | "NewType"]) - }) + semantic + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "TypeVar" | "NewType"])) } -pub(super) fn is_typed_dict_class(bases: &[Expr], semantic: &SemanticModel) -> bool { - bases - .iter() - .any(|base| semantic.match_typing_expr(base, "TypedDict")) +pub(super) fn is_typed_dict_class(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool { + arguments.is_some_and(|arguments| { + arguments + .args + .iter() + .any(|base| semantic.match_typing_expr(base, "TypedDict")) + }) } #[cfg(test)] diff --git a/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs b/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs index 91780d8cb0efc..74bb9de531108 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/error_suffix_on_exception_name.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -45,30 +45,33 @@ impl Violation for ErrorSuffixOnExceptionName { /// N818 pub(crate) fn error_suffix_on_exception_name( class_def: &Stmt, - bases: &[Expr], + arguments: Option<&Arguments>, name: &str, ignore_names: &[IdentifierPattern], ) -> Option { - if ignore_names - .iter() - .any(|ignore_name| ignore_name.matches(name)) - { + if name.ends_with("Error") { return None; } - if !bases.iter().any(|base| { - if let Expr::Name(ast::ExprName { id, .. }) = &base { - id == "Exception" || id.ends_with("Error") - } else { - false - } + if !arguments.is_some_and(|arguments| { + arguments.args.iter().any(|base| { + if let Expr::Name(ast::ExprName { id, .. }) = &base { + id == "Exception" || id.ends_with("Error") + } else { + false + } + }) }) { return None; } - if name.ends_with("Error") { + if ignore_names + .iter() + .any(|ignore_name| ignore_name.matches(name)) + { return None; } + Some(Diagnostic::new( ErrorSuffixOnExceptionName { name: name.to_string(), diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs index fa1c89b2502c6..e196920eb391e 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_argument_name.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arg, Ranged}; +use ruff_python_ast::{Parameter, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -50,7 +50,7 @@ impl Violation for InvalidArgumentName { /// N803 pub(crate) fn invalid_argument_name( name: &str, - arg: &Arg, + parameter: &Parameter, ignore_names: &[IdentifierPattern], ) -> Option { if ignore_names @@ -64,7 +64,7 @@ pub(crate) fn invalid_argument_name( InvalidArgumentName { name: name.to_string(), }, - arg.range(), + parameter.range(), )); } None diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_class_name.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_class_name.rs index f5eb7eeb80df3..005f04305cf28 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_class_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_class_name.rs @@ -62,7 +62,7 @@ pub(crate) fn invalid_class_name( } let stripped = name.strip_prefix('_').unwrap_or(name); - if !stripped.chars().next().map_or(false, char::is_uppercase) || stripped.contains('_') { + if !stripped.chars().next().is_some_and(char::is_uppercase) || stripped.contains('_') { return Some(Diagnostic::new( InvalidClassName { name: name.to_string(), diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs index e56168f6fae81..07cce7e9e75ae 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{ArgWithDefault, Arguments, Decorator, Ranged}; +use ruff_python_ast::{Decorator, ParameterWithDefault, Parameters, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -59,7 +59,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method( scope: &Scope, name: &str, decorator_list: &[Decorator], - args: &Arguments, + parameters: &Parameters, ) -> Option { if !matches!( function_type::classify( @@ -74,13 +74,16 @@ pub(crate) fn invalid_first_argument_name_for_class_method( ) { return None; } - if let Some(ArgWithDefault { - def, + if let Some(ParameterWithDefault { + parameter, default: _, range: _, - }) = args.posonlyargs.first().or_else(|| args.args.first()) + }) = parameters + .posonlyargs + .first() + .or_else(|| parameters.args.first()) { - if &def.arg != "cls" { + if ¶meter.name != "cls" { if checker .settings .pep8_naming @@ -92,7 +95,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method( } return Some(Diagnostic::new( InvalidFirstArgumentNameForClassMethod, - def.range(), + parameter.range(), )); } } diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs index dd517f70630ee..e3cbe3c49e1fe 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arguments, Decorator, Ranged}; +use ruff_python_ast::{Decorator, Parameters, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -57,7 +57,7 @@ pub(crate) fn invalid_first_argument_name_for_method( scope: &Scope, name: &str, decorator_list: &[Decorator], - args: &Arguments, + parameters: &Parameters, ) -> Option { if !matches!( function_type::classify( @@ -72,8 +72,11 @@ pub(crate) fn invalid_first_argument_name_for_method( ) { return None; } - let arg = args.posonlyargs.first().or_else(|| args.args.first())?; - if &arg.def.arg == "self" { + let arg = parameters + .posonlyargs + .first() + .or_else(|| parameters.args.first())?; + if &arg.parameter.name == "self" { return None; } if checker @@ -87,6 +90,6 @@ pub(crate) fn invalid_first_argument_name_for_method( } Some(Diagnostic::new( InvalidFirstArgumentNameForMethod, - arg.def.range(), + arg.parameter.range(), )) } diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_module_name.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_module_name.rs index c733db5e2fb32..62bdb4bd54f87 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_module_name.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_module_name.rs @@ -55,7 +55,7 @@ pub(crate) fn invalid_module_name( ) -> Option { if !path .extension() - .map_or(false, |ext| ext == "py" || ext == "pyi") + .is_some_and(|ext| ext == "py" || ext == "pyi") { return None; } @@ -97,7 +97,7 @@ pub(crate) fn invalid_module_name( /// Return `true` if a [`Path`] should use the name of its parent directory as its module name. fn is_module_file(path: &Path) -> bool { - path.file_name().map_or(false, |file_name| { + path.file_name().is_some_and(|file_name| { file_name == "__init__.py" || file_name == "__init__.pyi" || file_name == "__main__.py" @@ -110,5 +110,5 @@ fn is_migration_file(path: &Path) -> bool { path.parent() .and_then(Path::file_name) .and_then(OsStr::to_str) - .map_or(false, |parent| matches!(parent, "versions" | "migrations")) + .is_some_and(|parent| matches!(parent, "versions" | "migrations")) } diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs index e7ab035a702a5..ac796dfe7962b 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Expr, Ranged}; +use ruff_python_ast::{Arguments, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -54,7 +54,7 @@ pub(crate) fn mixed_case_variable_in_class_scope( checker: &mut Checker, expr: &Expr, name: &str, - bases: &[Expr], + arguments: Option<&Arguments>, ) { if checker .settings @@ -69,10 +69,10 @@ pub(crate) fn mixed_case_variable_in_class_scope( return; } - let parent = checker.semantic().stmt(); + let parent = checker.semantic().current_statement(); if helpers::is_named_tuple_assignment(parent, checker.semantic()) - || helpers::is_typed_dict_class(bases, checker.semantic()) + || helpers::is_typed_dict_class(arguments, checker.semantic()) { return; } diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs index a280e85286a8c..4eb648fe8f28d 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs @@ -75,7 +75,7 @@ pub(crate) fn mixed_case_variable_in_global_scope(checker: &mut Checker, expr: & return; } - let parent = checker.semantic().stmt(); + let parent = checker.semantic().current_statement(); if helpers::is_named_tuple_assignment(parent, checker.semantic()) { return; } diff --git a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs index 87383353aa95a..41a7fea0caed9 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs @@ -65,7 +65,7 @@ pub(crate) fn non_lowercase_variable_in_function(checker: &mut Checker, expr: &E return; } - let parent = checker.semantic().stmt(); + let parent = checker.semantic().current_statement(); if helpers::is_named_tuple_assignment(parent, checker.semantic()) || helpers::is_typed_dict_assignment(parent, checker.semantic()) || helpers::is_type_var_assignment(parent, checker.semantic()) diff --git a/crates/ruff/src/rules/pep8_naming/settings.rs b/crates/ruff/src/rules/pep8_naming/settings.rs index 5e8bbe23d3f49..0f67a8c19f08a 100644 --- a/crates/ruff/src/rules/pep8_naming/settings.rs +++ b/crates/ruff/src/rules/pep8_naming/settings.rs @@ -114,7 +114,7 @@ impl TryFrom for Settings { .ignore_names .unwrap_or_else(default_ignore_names) .into_iter() - .chain(options.extend_ignore_names.unwrap_or_default().into_iter()) + .chain(options.extend_ignore_names.unwrap_or_default()) .map(|name| IdentifierPattern::new(&name).map_err(SettingsError::InvalidIgnoreName)) .collect::, Self::Error>>()?, classmethod_decorators: options.classmethod_decorators.unwrap_or_default(), diff --git a/crates/ruff/src/rules/perflint/mod.rs b/crates/ruff/src/rules/perflint/mod.rs index 291bfcd207ca2..3e196d479dd0a 100644 --- a/crates/ruff/src/rules/perflint/mod.rs +++ b/crates/ruff/src/rules/perflint/mod.rs @@ -10,6 +10,7 @@ mod tests { use crate::assert_messages; use crate::registry::Rule; + use crate::settings::types::PythonVersion; use crate::settings::Settings; use crate::test::test_path; @@ -22,7 +23,7 @@ mod tests { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( Path::new("perflint").join(path).as_path(), - &Settings::for_rule(rule_code), + &Settings::for_rule(rule_code).with_target_version(PythonVersion::Py310), )?; assert_messages!(snapshot, diagnostics); Ok(()) diff --git a/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs b/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs index 5b6e416aeea23..8d25a2509dab6 100644 --- a/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs +++ b/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs @@ -1,11 +1,10 @@ use std::fmt; -use ruff_python_ast as ast; -use ruff_python_ast::Expr; -use ruff_python_ast::Ranged; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast as ast; +use ruff_python_ast::Ranged; +use ruff_python_ast::{Arguments, Expr}; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; @@ -58,14 +57,19 @@ impl AlwaysAutofixableViolation for IncorrectDictIterator { } /// PERF102 -pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, target: &Expr, iter: &Expr) { - let Expr::Tuple(ast::ExprTuple { elts, .. }) = target else { +pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, stmt_for: &ast::StmtFor) { + let Expr::Tuple(ast::ExprTuple { elts, .. }) = stmt_for.target.as_ref() else { return; }; let [key, value] = elts.as_slice() else { return; }; - let Expr::Call(ast::ExprCall { func, args, .. }) = iter else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) = stmt_for.iter.as_ref() + else { return; }; if !args.is_empty() { @@ -100,7 +104,7 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, target: &Expr, iter let replace_attribute = Edit::range_replacement("values".to_string(), attr.range()); let replace_target = Edit::range_replacement( checker.locator().slice(value.range()).to_string(), - target.range(), + stmt_for.target.range(), ); diagnostic.set_fix(Fix::suggested_edits(replace_attribute, [replace_target])); } @@ -118,7 +122,7 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, target: &Expr, iter let replace_attribute = Edit::range_replacement("keys".to_string(), attr.range()); let replace_target = Edit::range_replacement( checker.locator().slice(key.range()).to_string(), - target.range(), + stmt_for.target.range(), ); diagnostic.set_fix(Fix::suggested_edits(replace_attribute, [replace_target])); } @@ -143,9 +147,11 @@ impl fmt::Display for DictSubset { } /// Returns `true` if the given expression is either an unused value or a tuple of unused values. -fn is_unused(expr: &Expr, model: &SemanticModel) -> bool { +fn is_unused(expr: &Expr, semantic: &SemanticModel) -> bool { match expr { - Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(|expr| is_unused(expr, model)), + Expr::Tuple(ast::ExprTuple { elts, .. }) => { + elts.iter().all(|expr| is_unused(expr, semantic)) + } Expr::Name(ast::ExprName { id, .. }) => { // Treat a variable as used if it has any usages, _or_ it's shadowed by another variable // with usages. @@ -162,11 +168,11 @@ fn is_unused(expr: &Expr, model: &SemanticModel) -> bool { // // print(bar) // ``` - let scope = model.scope(); + let scope = semantic.current_scope(); scope .get_all(id) - .map(|binding_id| model.binding(binding_id)) - .filter(|binding| binding.range.start() >= expr.range().start()) + .map(|binding_id| semantic.binding(binding_id)) + .filter(|binding| binding.start() >= expr.start()) .all(|binding| !binding.is_used()) } _ => false, diff --git a/crates/ruff/src/rules/perflint/rules/manual_list_comprehension.rs b/crates/ruff/src/rules/perflint/rules/manual_list_comprehension.rs index 1f9f287edfcd9..d3d4476b8fdd1 100644 --- a/crates/ruff/src/rules/perflint/rules/manual_list_comprehension.rs +++ b/crates/ruff/src/rules/perflint/rules/manual_list_comprehension.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -92,9 +92,13 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo let Expr::Call(ast::ExprCall { func, + arguments: + Arguments { + args, + keywords, + range: _, + }, range, - args, - keywords, }) = value.as_ref() else { return; @@ -110,7 +114,7 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo // Ignore direct list copies (e.g., `for x in y: filtered.append(x)`). if if_test.is_none() { - if arg.as_name_expr().map_or(false, |arg| arg.id == *id) { + if arg.as_name_expr().is_some_and(|arg| arg.id == *id) { return; } } @@ -125,7 +129,7 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo // Avoid, e.g., `for x in y: filtered[x].append(x * x)`. if any_over_expr(value, &|expr| { - expr.as_name_expr().map_or(false, |expr| expr.id == *id) + expr.as_name_expr().is_some_and(|expr| expr.id == *id) }) { return; } @@ -152,10 +156,10 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo // filtered = [x for x in y if x in filtered] // ``` if let Some(value_name) = value.as_name_expr() { - if if_test.map_or(false, |test| { + if if_test.is_some_and(|test| { any_over_expr(test, &|expr| { expr.as_name_expr() - .map_or(false, |expr| expr.id == value_name.id) + .is_some_and(|expr| expr.id == value_name.id) }) }) { return; diff --git a/crates/ruff/src/rules/perflint/rules/manual_list_copy.rs b/crates/ruff/src/rules/perflint/rules/manual_list_copy.rs index 902fb2138b42f..7e12dccf7619e 100644 --- a/crates/ruff/src/rules/perflint/rules/manual_list_copy.rs +++ b/crates/ruff/src/rules/perflint/rules/manual_list_copy.rs @@ -1,7 +1,7 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::any_over_expr; -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Arguments, Expr, Stmt}; use crate::checkers::ast::Checker; @@ -59,9 +59,13 @@ pub(crate) fn manual_list_copy(checker: &mut Checker, target: &Expr, body: &[Stm let Expr::Call(ast::ExprCall { func, + arguments: + Arguments { + args, + keywords, + range: _, + }, range, - args, - keywords, }) = value.as_ref() else { return; @@ -76,7 +80,7 @@ pub(crate) fn manual_list_copy(checker: &mut Checker, target: &Expr, body: &[Stm }; // Only flag direct list copies (e.g., `for x in y: filtered.append(x)`). - if !arg.as_name_expr().map_or(false, |arg| arg.id == *id) { + if !arg.as_name_expr().is_some_and(|arg| arg.id == *id) { return; } @@ -90,7 +94,7 @@ pub(crate) fn manual_list_copy(checker: &mut Checker, target: &Expr, body: &[Stm // Avoid, e.g., `for x in y: filtered[x].append(x)`. if any_over_expr(value, &|expr| { - expr.as_name_expr().map_or(false, |expr| expr.id == *id) + expr.as_name_expr().is_some_and(|expr| expr.id == *id) }) { return; } diff --git a/crates/ruff/src/rules/perflint/rules/try_except_in_loop.rs b/crates/ruff/src/rules/perflint/rules/try_except_in_loop.rs index ffa8a428faa3e..84e14e5386a6a 100644 --- a/crates/ruff/src/rules/perflint/rules/try_except_in_loop.rs +++ b/crates/ruff/src/rules/perflint/rules/try_except_in_loop.rs @@ -1,7 +1,7 @@ -use ruff_python_ast::{self as ast, Ranged, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::statement_visitor::{walk_stmt, StatementVisitor}; +use ruff_python_ast::{self as ast, Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::settings::types::PythonVersion; @@ -35,6 +35,7 @@ use crate::settings::types::PythonVersion; /// int_numbers.append(int(num)) /// except ValueError as e: /// print(f"Couldn't convert to integer: {e}") +/// break /// ``` /// /// Use instead: @@ -67,7 +68,7 @@ pub(crate) fn try_except_in_loop(checker: &mut Checker, body: &[Stmt]) { return; } - let [Stmt::Try(ast::StmtTry { handlers, .. })] = body else { + let [Stmt::Try(ast::StmtTry { handlers, body, .. })] = body else { return; }; @@ -75,7 +76,37 @@ pub(crate) fn try_except_in_loop(checker: &mut Checker, body: &[Stmt]) { return; }; + // Avoid flagging `try`-`except` blocks that contain `break` or `continue`, + // which rely on the exception handling mechanism. + if has_break_or_continue(body) { + return; + } + checker .diagnostics .push(Diagnostic::new(TryExceptInLoop, handler.range())); } + +/// Returns `true` if a `break` or `continue` statement is present in `body`. +fn has_break_or_continue(body: &[Stmt]) -> bool { + let mut visitor = LoopControlFlowVisitor::default(); + visitor.visit_body(body); + visitor.has_break_or_continue +} + +#[derive(Debug, Default)] +struct LoopControlFlowVisitor { + has_break_or_continue: bool, +} + +impl StatementVisitor<'_> for LoopControlFlowVisitor { + fn visit_stmt(&mut self, stmt: &Stmt) { + match stmt { + Stmt::Break(_) | Stmt::Continue(_) => self.has_break_or_continue = true, + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { + // Don't recurse. + } + _ => walk_stmt(self, stmt), + } + } +} diff --git a/crates/ruff/src/rules/perflint/rules/unnecessary_list_cast.rs b/crates/ruff/src/rules/perflint/rules/unnecessary_list_cast.rs index 45a6a32da3dc3..94385fca3b6bc 100644 --- a/crates/ruff/src/rules/perflint/rules/unnecessary_list_cast.rs +++ b/crates/ruff/src/rules/perflint/rules/unnecessary_list_cast.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr}; +use ruff_python_ast::{self as ast, Arguments, Expr}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -54,17 +54,21 @@ impl AlwaysAutofixableViolation for UnnecessaryListCast { pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) { let Expr::Call(ast::ExprCall { func, - args, + arguments: + Arguments { + args, + keywords: _, + range: _, + }, range: list_range, - .. }) = iter else { return; }; - if args.len() != 1 { + let [arg] = args.as_slice() else { return; - } + }; let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else { return; @@ -74,7 +78,7 @@ pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) { return; } - match &args[0] { + match arg { Expr::Tuple(ast::ExprTuple { range: iterable_range, .. @@ -98,12 +102,12 @@ pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) { range: iterable_range, .. }) => { - let scope = checker.semantic().scope(); + let scope = checker.semantic().current_scope(); if let Some(binding_id) = scope.get(id) { let binding = checker.semantic().binding(binding_id); if binding.kind.is_assignment() || binding.kind.is_named_expr_assignment() { if let Some(parent_id) = binding.source { - let parent = checker.semantic().stmts[parent_id]; + let parent = checker.semantic().statement(parent_id); if let Stmt::Assign(ast::StmtAssign { value, .. }) | Stmt::AnnAssign(ast::StmtAnnAssign { value: Some(value), .. diff --git a/crates/ruff/src/rules/pycodestyle/helpers.rs b/crates/ruff/src/rules/pycodestyle/helpers.rs index 12ae3a0a39ac7..46b728b224533 100644 --- a/crates/ruff/src/rules/pycodestyle/helpers.rs +++ b/crates/ruff/src/rules/pycodestyle/helpers.rs @@ -1,8 +1,10 @@ -use ruff_python_ast::{CmpOp, Expr, Ranged}; -use ruff_text_size::{TextLen, TextRange}; use unicode_width::UnicodeWidthStr; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::{CmpOp, Expr, Ranged}; use ruff_source_file::{Line, Locator}; +use ruff_text_size::{TextLen, TextRange}; use crate::line_width::{LineLength, LineWidth, TabSize}; @@ -10,10 +12,11 @@ pub(super) fn is_ambiguous_name(name: &str) -> bool { name == "l" || name == "I" || name == "O" } -pub(super) fn compare( +pub(super) fn generate_comparison( left: &Expr, ops: &[CmpOp], comparators: &[Expr], + parent: AnyNodeRef, locator: &Locator, ) -> String { let start = left.start(); @@ -21,7 +24,9 @@ pub(super) fn compare( let mut contents = String::with_capacity(usize::from(end - start)); // Add the left side of the comparison. - contents.push_str(locator.slice(left.range())); + contents.push_str(locator.slice( + parenthesized_range(left.into(), parent, locator.contents()).unwrap_or(left.range()), + )); for (op, comparator) in ops.iter().zip(comparators) { // Add the operator. @@ -39,7 +44,12 @@ pub(super) fn compare( }); // Add the right side of the comparison. - contents.push_str(locator.slice(comparator.range())); + contents.push_str( + locator.slice( + parenthesized_range(comparator.into(), parent, locator.contents()) + .unwrap_or(comparator.range()), + ), + ); } contents @@ -52,8 +62,11 @@ pub(super) fn is_overlong( task_tags: &[String], tab_size: TabSize, ) -> Option { - // Each character is between 1-4 bytes. If the number of bytes is smaller than the limit, it cannot be overlong. - if line.len() < limit.get() { + // The maximum width of the line is the number of bytes multiplied by the tab size (the + // worst-case scenario is that the line is all tabs). If the maximum width is less than the + // limit, then the line is not overlong. + let max_width = line.len() * tab_size.as_usize(); + if max_width < limit.get() { return None; } diff --git a/crates/ruff/src/rules/pycodestyle/mod.rs b/crates/ruff/src/rules/pycodestyle/mod.rs index 9810feb01cfac..95495cbae70a9 100644 --- a/crates/ruff/src/rules/pycodestyle/mod.rs +++ b/crates/ruff/src/rules/pycodestyle/mod.rs @@ -6,6 +6,7 @@ pub(crate) mod helpers; #[cfg(test)] mod tests { + use std::num::NonZeroU8; use std::path::Path; use anyhow::Result; @@ -204,7 +205,8 @@ mod tests { let diagnostics = test_path( Path::new("pycodestyle/E501_2.py"), &settings::Settings { - tab_size: tab_size.into(), + tab_size: NonZeroU8::new(tab_size).unwrap().into(), + line_length: LineLength::from(6), ..settings::Settings::for_rule(Rule::LineTooLong) }, )?; diff --git a/crates/ruff/src/rules/pycodestyle/rules/errors.rs b/crates/ruff/src/rules/pycodestyle/rules/errors.rs index 213de95dfcbfd..da02f458a8cbd 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/errors.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/errors.rs @@ -7,6 +7,28 @@ use ruff_source_file::Locator; use crate::logging::DisplayParseErrorType; +/// ## What it does +/// This is not a regular diagnostic; instead, it's raised when a file cannot be read +/// from disk. +/// +/// ## Why is this bad? +/// An `IOError` indicates an error in the development setup. For example, the user may +/// not have permissions to read a given file, or the filesystem may contain a broken +/// symlink. +/// +/// ## Example +/// On Linux or macOS: +/// ```shell +/// $ echo 'print("hello world!")' > a.py +/// $ chmod 000 a.py +/// $ ruff a.py +/// a.py:1:1: E902 Permission denied (os error 13) +/// Found 1 error. +/// ``` +/// +/// ## References +/// - [UNIX Permissions introduction](https://mason.gmu.edu/~montecin/UNIXpermiss.htm) +/// - [Command Line Basics: Symbolic Links](https://www.digitalocean.com/community/tutorials/workflow-symbolic-links) #[violation] pub struct IOError { pub message: String, @@ -21,6 +43,25 @@ impl Violation for IOError { } } +/// ## What it does +/// Checks for code that contains syntax errors. +/// +/// ## Why is this bad? +/// Code with syntax errors cannot be executed. Such errors are likely a +/// mistake. +/// +/// ## Example +/// ```python +/// x = +/// ``` +/// +/// Use instead: +/// ```python +/// x = 1 +/// ``` +/// +/// ## References +/// - [Python documentation: Syntax Errors](https://docs.python.org/3/tutorial/errors.html#syntax-errors) #[violation] pub struct SyntaxError { pub message: String, diff --git a/crates/ruff/src/rules/pycodestyle/rules/imports.rs b/crates/ruff/src/rules/pycodestyle/rules/imports.rs index 4085b6aa66672..8e20077d34ac3 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/imports.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/imports.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{Alias, Ranged, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_source_file::Locator; +use ruff_python_ast::{Alias, Ranged, Stmt}; use crate::checkers::ast::Checker; @@ -81,12 +79,8 @@ pub(crate) fn multiple_imports_on_one_line(checker: &mut Checker, stmt: &Stmt, n } /// E402 -pub(crate) fn module_import_not_at_top_of_file( - checker: &mut Checker, - stmt: &Stmt, - locator: &Locator, -) { - if checker.semantic().seen_import_boundary() && locator.is_at_start_of_line(stmt.start()) { +pub(crate) fn module_import_not_at_top_of_file(checker: &mut Checker, stmt: &Stmt) { + if checker.semantic().seen_import_boundary() && checker.semantic().at_top_level() { checker .diagnostics .push(Diagnostic::new(ModuleImportNotAtTopOfFile, stmt.range())); diff --git a/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs b/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs index fbe8e1bff3f4b..2cea1ad2f15d9 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs @@ -68,7 +68,7 @@ pub(crate) fn invalid_escape_sequence( let bytes = body.as_bytes(); for i in memchr_iter(b'\\', bytes) { // If the previous character was also a backslash, skip. - if prev.map_or(false, |prev| prev == i - 1) { + if prev.is_some_and(|prev| prev == i - 1) { prev = None; continue; } @@ -129,7 +129,7 @@ pub(crate) fn invalid_escape_sequence( for diagnostic in &mut invalid_escape_sequence { diagnostic.set_fix(Fix::automatic(Edit::insertion( r"\".to_string(), - diagnostic.range().start() + TextSize::from(1), + diagnostic.start() + TextSize::from(1), ))); } } else { @@ -142,7 +142,7 @@ pub(crate) fn invalid_escape_sequence( .slice(TextRange::up_to(range.start())) .chars() .last() - .map_or(false, |char| char.is_ascii_alphabetic()); + .is_some_and(|char| char.is_ascii_alphabetic()); diagnostic.set_fix(Fix::automatic(Edit::insertion( if requires_space { diff --git a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs index 663a84ba319f1..2ad00759e5c63 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -1,5 +1,6 @@ use ruff_python_ast::{ - self as ast, Arg, ArgWithDefault, Arguments, Constant, Expr, Identifier, Ranged, Stmt, + self as ast, Constant, Expr, Identifier, Parameter, ParameterWithDefault, Parameters, Ranged, + Stmt, }; use ruff_text_size::TextRange; @@ -67,7 +68,10 @@ pub(crate) fn lambda_assignment( return; }; - let Expr::Lambda(ast::ExprLambda { args, body, .. }) = value else { + let Expr::Lambda(ast::ExprLambda { + parameters, body, .. + }) = value + else { return; }; @@ -87,7 +91,7 @@ pub(crate) fn lambda_assignment( let mut indented = String::new(); for (idx, line) in function( id, - args, + parameters.as_deref(), body, annotation, checker.semantic(), @@ -108,14 +112,17 @@ pub(crate) fn lambda_assignment( // If the assignment is in a class body, it might not be safe to replace it because the // assignment might be carrying a type annotation that will be used by some package like // dataclasses, which wouldn't consider the rewritten function definition to be - // equivalent. Similarly, if the lambda is shadowing a variable in the current scope, - // rewriting it as a function declaration may break type-checking. + // equivalent. Even if it _doesn't_ have an annotation, rewriting safely would require + // making this a static method. // See: https://github.com/astral-sh/ruff/issues/3046 + // + // Similarly, if the lambda is shadowing a variable in the current scope, + // rewriting it as a function declaration may break type-checking. // See: https://github.com/astral-sh/ruff/issues/5421 - if (annotation.is_some() && checker.semantic().scope().kind.is_class()) + if checker.semantic().current_scope().kind.is_class() || checker .semantic() - .scope() + .current_scope() .get_all(id) .any(|binding_id| checker.semantic().binding(binding_id).kind.is_annotation()) { @@ -147,13 +154,10 @@ fn extract_types(annotation: &Expr, semantic: &SemanticModel) -> Option<(Vec Option<(Vec, body: &Expr, annotation: Option<&Expr>, semantic: &SemanticModel, @@ -186,61 +190,66 @@ fn function( value: Some(Box::new(body.clone())), range: TextRange::default(), }); + let parameters = parameters + .cloned() + .unwrap_or_else(|| Parameters::empty(TextRange::default())); if let Some(annotation) = annotation { if let Some((arg_types, return_type)) = extract_types(annotation, semantic) { // A `lambda` expression can only have positional and positional-only // arguments. The order is always positional-only first, then positional. - let new_posonlyargs = args + let new_posonlyargs = parameters .posonlyargs .iter() .enumerate() - .map(|(idx, arg_with_default)| ArgWithDefault { - def: Arg { + .map(|(idx, parameter)| ParameterWithDefault { + parameter: Parameter { annotation: arg_types .get(idx) .map(|arg_type| Box::new(arg_type.clone())), - ..arg_with_default.def.clone() + ..parameter.parameter.clone() }, - ..arg_with_default.clone() + ..parameter.clone() }) .collect::>(); - let new_args = args + let new_args = parameters .args .iter() .enumerate() - .map(|(idx, arg_with_default)| ArgWithDefault { - def: Arg { + .map(|(idx, parameter)| ParameterWithDefault { + parameter: Parameter { annotation: arg_types .get(idx + new_posonlyargs.len()) .map(|arg_type| Box::new(arg_type.clone())), - ..arg_with_default.def.clone() + ..parameter.parameter.clone() }, - ..arg_with_default.clone() + ..parameter.clone() }) .collect::>(); let func = Stmt::FunctionDef(ast::StmtFunctionDef { + is_async: false, name: Identifier::new(name.to_string(), TextRange::default()), - args: Box::new(Arguments { + parameters: Box::new(Parameters { posonlyargs: new_posonlyargs, args: new_args, - ..args.clone() + ..parameters }), body: vec![body], decorator_list: vec![], returns: Some(Box::new(return_type)), - type_params: vec![], + type_params: None, range: TextRange::default(), }); return generator.stmt(&func); } } let func = Stmt::FunctionDef(ast::StmtFunctionDef { + is_async: false, name: Identifier::new(name.to_string(), TextRange::default()), - args: Box::new(args.clone()), + parameters: Box::new(parameters), body: vec![body], decorator_list: vec![], returns: None, - type_params: vec![], + type_params: None, range: TextRange::default(), }); generator.stmt(&func) diff --git a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs index 1a75983d89854..9c7f525b6ca72 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs @@ -1,15 +1,15 @@ -use itertools::izip; -use ruff_python_ast::{self as ast, CmpOp, Constant, Expr, Ranged}; use rustc_hash::FxHashMap; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers; use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, CmpOp, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; +use crate::codes::Rule; use crate::registry::AsRule; -use crate::rules::pycodestyle::helpers::compare; +use crate::rules::pycodestyle::helpers::generate_comparison; #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum EqCmpOp { @@ -130,15 +130,7 @@ impl AlwaysAutofixableViolation for TrueFalseComparison { } /// E711, E712 -pub(crate) fn literal_comparisons( - checker: &mut Checker, - expr: &Expr, - left: &Expr, - ops: &[CmpOp], - comparators: &[Expr], - check_none_comparisons: bool, - check_true_false_comparisons: bool, -) { +pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprCompare) { // Mapping from (bad operator index) to (replacement operator). As we iterate // through the list of operators, we apply "dummy" fixes for each error, // then replace the entire expression at the end with one "real" fix, to @@ -146,15 +138,18 @@ pub(crate) fn literal_comparisons( let mut bad_ops: FxHashMap = FxHashMap::default(); let mut diagnostics: Vec = vec![]; - let op = ops.first().unwrap(); - // Check `left`. - let mut comparator = left; - let next = &comparators[0]; + let mut comparator = compare.left.as_ref(); + let [op, ..] = compare.ops.as_slice() else { + return; + }; + let [next, ..] = compare.comparators.as_slice() else { + return; + }; if !helpers::is_constant_non_singleton(next) { if let Some(op) = EqCmpOp::try_from(*op) { - if check_none_comparisons && is_const_none(comparator) { + if checker.enabled(Rule::NoneComparison) && is_const_none(comparator) { match op { EqCmpOp::Eq => { let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range()); @@ -173,7 +168,7 @@ pub(crate) fn literal_comparisons( } } - if check_true_false_comparisons { + if checker.enabled(Rule::TrueFalseComparison) { if let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), kind: None, @@ -208,59 +203,66 @@ pub(crate) fn literal_comparisons( } // Check each comparator in order. - for (idx, (op, next)) in izip!(ops, comparators).enumerate() { + for (index, (op, next)) in compare + .ops + .iter() + .zip(compare.comparators.iter()) + .enumerate() + { if helpers::is_constant_non_singleton(comparator) { comparator = next; continue; } - if let Some(op) = EqCmpOp::try_from(*op) { - if check_none_comparisons && is_const_none(next) { + let Some(op) = EqCmpOp::try_from(*op) else { + continue; + }; + + if checker.enabled(Rule::NoneComparison) && is_const_none(next) { + match op { + EqCmpOp::Eq => { + let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); + if checker.patch(diagnostic.kind.rule()) { + bad_ops.insert(index, CmpOp::Is); + } + diagnostics.push(diagnostic); + } + EqCmpOp::NotEq => { + let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); + if checker.patch(diagnostic.kind.rule()) { + bad_ops.insert(index, CmpOp::IsNot); + } + diagnostics.push(diagnostic); + } + } + } + + if checker.enabled(Rule::TrueFalseComparison) { + if let Expr::Constant(ast::ExprConstant { + value: Constant::Bool(value), + kind: None, + range: _, + }) = next + { match op { EqCmpOp::Eq => { - let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); + let diagnostic = + Diagnostic::new(TrueFalseComparison(*value, op), next.range()); if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(idx, CmpOp::Is); + bad_ops.insert(index, CmpOp::Is); } diagnostics.push(diagnostic); } EqCmpOp::NotEq => { - let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); + let diagnostic = + Diagnostic::new(TrueFalseComparison(*value, op), next.range()); if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(idx, CmpOp::IsNot); + bad_ops.insert(index, CmpOp::IsNot); } diagnostics.push(diagnostic); } } } - - if check_true_false_comparisons { - if let Expr::Constant(ast::ExprConstant { - value: Constant::Bool(value), - kind: None, - range: _, - }) = next - { - match op { - EqCmpOp::Eq => { - let diagnostic = - Diagnostic::new(TrueFalseComparison(*value, op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(idx, CmpOp::Is); - } - diagnostics.push(diagnostic); - } - EqCmpOp::NotEq => { - let diagnostic = - Diagnostic::new(TrueFalseComparison(*value, op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(idx, CmpOp::IsNot); - } - diagnostics.push(diagnostic); - } - } - } - } } comparator = next; @@ -270,17 +272,24 @@ pub(crate) fn literal_comparisons( // `noqa`, but another doesn't, both will be removed here. if !bad_ops.is_empty() { // Replace the entire comparison expression. - let ops = ops + let ops = compare + .ops .iter() .enumerate() .map(|(idx, op)| bad_ops.get(&idx).unwrap_or(op)) .copied() .collect::>(); - let content = compare(left, &ops, comparators, checker.locator()); + let content = generate_comparison( + &compare.left, + &ops, + &compare.comparators, + compare.into(), + checker.locator(), + ); for diagnostic in &mut diagnostics { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( content.to_string(), - expr.range(), + compare.range(), ))); } } diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs index 58a7446e72048..94bbd34e2f4b8 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs @@ -3,6 +3,7 @@ use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Edit; use ruff_diagnostics::Fix; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; use ruff_text_size::TextRange; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/indentation.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/indentation.rs index 5146734ef1846..ea4f592881023 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/indentation.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/indentation.rs @@ -247,7 +247,7 @@ pub(crate) fn indentation( } let indent_expect = prev_logical_line .and_then(|prev_logical_line| prev_logical_line.tokens_trimmed().last()) - .map_or(false, |t| t.kind() == TokenKind::Colon); + .is_some_and(|t| t.kind() == TokenKind::Colon); if indent_expect && indent_level <= prev_indent_level.unwrap_or(0) { diagnostics.push(if logical_line.is_comment_only() { @@ -256,7 +256,7 @@ pub(crate) fn indentation( DiagnosticKind::from(NoIndentedBlock) }); } else if !indent_expect - && prev_indent_level.map_or(false, |prev_indent_level| indent_level > prev_indent_level) + && prev_indent_level.is_some_and(|prev_indent_level| indent_level > prev_indent_level) { diagnostics.push(if logical_line.is_comment_only() { DiagnosticKind::from(UnexpectedIndentationComment) diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs index 6820eb44c1755..6c90b80bc9c62 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs @@ -1,14 +1,29 @@ -use ruff_text_size::TextSize; - use ruff_diagnostics::Edit; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; +use ruff_text_size::TextSize; use crate::checkers::logical_lines::LogicalLinesContext; use super::LogicalLine; +/// ## What it does +/// Checks for missing whitespace after `,`, `;`, and `:`. +/// +/// ## Why is this bad? +/// Missing whitespace after `,`, `;`, and `:` makes the code harder to read. +/// +/// ## Example +/// ```python +/// a = (1,2) +/// ``` +/// +/// Use instead: +/// ```python +/// a = (1, 2) +/// ``` #[violation] pub struct MissingWhitespace { token: TokenKind, @@ -66,10 +81,10 @@ pub(crate) fn missing_whitespace( TokenKind::Comma | TokenKind::Semi | TokenKind::Colon => { let after = line.text_after(token); - if !after + if after .chars() .next() - .map_or(false, |c| char::is_whitespace(c) || c == '\\') + .is_some_and(|c| !(char::is_whitespace(c) || c == '\\')) { if let Some(next_token) = iter.peek() { match (kind, next_token.kind()) { diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs index 0fac3492a6014..c0df9e5d210de 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs @@ -1,10 +1,31 @@ use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; use crate::checkers::logical_lines::LogicalLinesContext; use crate::rules::pycodestyle::rules::logical_lines::LogicalLine; +/// ## What it does +/// Checks for missing whitespace after keywords. +/// +/// ## Why is this bad? +/// Missing whitespace after keywords makes the code harder to read. +/// +/// ## Example +/// ```python +/// if(True): +/// pass +/// ``` +/// +/// Use instead: +/// ```python +/// if (True): +/// pass +/// ``` +/// +/// ## References +/// - [Python documentation: Keywords](https://docs.python.org/3/reference/lexical_analysis.html#keywords) #[violation] pub struct MissingWhitespaceAfterKeyword; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs index a32a4e4bd90e3..ea1764daf0ba2 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{DiagnosticKind, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; use crate::checkers::logical_lines::LogicalLinesContext; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/mod.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/mod.rs index e20fad75aee10..60fbb03998271 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/mod.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/mod.rs @@ -13,6 +13,7 @@ use std::fmt::{Debug, Formatter}; use std::iter::FusedIterator; use bitflags::bitflags; +use ruff_python_ast::Ranged; use ruff_python_parser::lexer::LexResult; use ruff_text_size::{TextLen, TextRange, TextSize}; @@ -310,22 +311,11 @@ impl LogicalLineToken { pub(crate) const fn kind(&self) -> TokenKind { self.kind } +} - /// Returns the token's start location - #[inline] - pub(crate) const fn start(&self) -> TextSize { - self.range.start() - } - - /// Returns the token's end location - #[inline] - pub(crate) const fn end(&self) -> TextSize { - self.range.end() - } - +impl Ranged for LogicalLineToken { /// Returns a tuple with the token's `(start, end)` locations - #[inline] - pub(crate) const fn range(&self) -> TextRange { + fn range(&self) -> TextRange { self.range } } diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/space_around_operator.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/space_around_operator.rs index c6c4b7dcdea59..e8347d18c7624 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/space_around_operator.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/space_around_operator.rs @@ -1,8 +1,8 @@ -use ruff_text_size::TextRange; - use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; +use ruff_text_size::TextRange; use crate::checkers::logical_lines::LogicalLinesContext; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_keywords.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_keywords.rs index 5c87d7df30c88..2a2af9a0f1db4 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_keywords.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_keywords.rs @@ -1,7 +1,7 @@ -use ruff_text_size::TextRange; - use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; +use ruff_text_size::TextRange; use crate::checkers::logical_lines::LogicalLinesContext; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_named_parameter_equals.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_named_parameter_equals.rs index 1b6a8f14a98e5..d7af34968ef4c 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_named_parameter_equals.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_around_named_parameter_equals.rs @@ -1,12 +1,37 @@ -use ruff_text_size::{TextRange, TextSize}; - use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; +use ruff_text_size::{TextRange, TextSize}; use crate::checkers::logical_lines::LogicalLinesContext; use crate::rules::pycodestyle::rules::logical_lines::{LogicalLine, LogicalLineToken}; +/// ## What it does +/// Checks for missing whitespace around the equals sign in an unannotated +/// function keyword parameter. +/// +/// ## Why is this bad? +/// According to [PEP 8], there should be no spaces around the equals sign in a +/// keyword parameter, if it is unannotated: +/// +/// > Don’t use spaces around the = sign when used to indicate a keyword +/// > argument, or when used to indicate a default value for an unannotated +/// > function parameter. +/// +/// ## Example +/// ```python +/// def add(a = 0) -> int: +/// return a + 1 +/// ``` +/// +/// Use instead: +/// ```python +/// def add(a = 0) -> int: +/// return a + 1 +/// ``` +/// +/// [PEP 8]: https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements #[violation] pub struct UnexpectedSpacesAroundKeywordParameterEquals; @@ -17,6 +42,31 @@ impl Violation for UnexpectedSpacesAroundKeywordParameterEquals { } } +/// ## What it does +/// Checks for missing whitespace around the equals sign in an annotated +/// function keyword parameter. +/// +/// ## Why is this bad? +/// According to [PEP 8], the spaces around the equals sign in a keyword +/// parameter should only be omitted when the parameter is unannotated: +/// +/// > Don’t use spaces around the = sign when used to indicate a keyword +/// > argument, or when used to indicate a default value for an unannotated +/// > function parameter. +/// +/// ## Example +/// ```python +/// def add(a: int=0) -> int: +/// return a + 1 +/// ``` +/// +/// Use instead: +/// ```python +/// def add(a: int = 0) -> int: +/// return a + 1 +/// ``` +/// +/// [PEP 8]: https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements #[violation] pub struct MissingWhitespaceAroundParameterEquals; diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_comment.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_comment.rs index 87084053d4ec7..f6b1a9f4f72a7 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_comment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_comment.rs @@ -1,10 +1,10 @@ -use ruff_text_size::{TextLen, TextRange, TextSize}; - use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; use ruff_python_trivia::PythonWhitespace; use ruff_source_file::Locator; +use ruff_text_size::{TextLen, TextRange, TextSize}; use crate::checkers::logical_lines::LogicalLinesContext; use crate::rules::pycodestyle::rules::logical_lines::LogicalLine; @@ -175,8 +175,7 @@ pub(crate) fn whitespace_before_comment( }; if is_inline_comment { - if bad_prefix.is_some() || comment.chars().next().map_or(false, char::is_whitespace) - { + if bad_prefix.is_some() || comment.chars().next().is_some_and(char::is_whitespace) { context.push(NoSpaceAfterInlineComment, range); } } else if let Some(bad_prefix) = bad_prefix { diff --git a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs index 1fea887220343..0d3c6fe32f58c 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs @@ -1,8 +1,8 @@ -use ruff_text_size::{TextRange, TextSize}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_parser::TokenKind; +use ruff_text_size::{TextRange, TextSize}; use crate::checkers::logical_lines::LogicalLinesContext; use crate::rules::pycodestyle::rules::logical_lines::LogicalLine; diff --git a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs index e77c1ebfa1e52..7aba04d41aa0e 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs @@ -1,11 +1,10 @@ -use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged, UnaryOp}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; -use crate::rules::pycodestyle::helpers::compare; +use crate::registry::{AsRule, Rule}; +use crate::rules::pycodestyle::helpers::generate_comparison; /// ## What it does /// Checks for negative comparison using `not {foo} in {bar}`. @@ -74,54 +73,58 @@ impl AlwaysAutofixableViolation for NotIsTest { } /// E713, E714 -pub(crate) fn not_tests( - checker: &mut Checker, - expr: &Expr, - op: UnaryOp, - operand: &Expr, - check_not_in: bool, - check_not_is: bool, -) { - if matches!(op, UnaryOp::Not) { - if let Expr::Compare(ast::ExprCompare { - left, - ops, - comparators, - range: _, - }) = operand - { - if !matches!(&ops[..], [CmpOp::In | CmpOp::Is]) { - return; +pub(crate) fn not_tests(checker: &mut Checker, unary_op: &ast::ExprUnaryOp) { + if !unary_op.op.is_not() { + return; + } + + let Expr::Compare(ast::ExprCompare { + left, + ops, + comparators, + range: _, + }) = unary_op.operand.as_ref() + else { + return; + }; + + match ops.as_slice() { + [CmpOp::In] => { + if checker.enabled(Rule::NotInTest) { + let mut diagnostic = Diagnostic::new(NotInTest, unary_op.operand.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.set_fix(Fix::automatic(Edit::range_replacement( + generate_comparison( + left, + &[CmpOp::NotIn], + comparators, + unary_op.into(), + checker.locator(), + ), + unary_op.range(), + ))); + } + checker.diagnostics.push(diagnostic); } - for op in ops { - match op { - CmpOp::In => { - if check_not_in { - let mut diagnostic = Diagnostic::new(NotInTest, operand.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - compare(left, &[CmpOp::NotIn], comparators, checker.locator()), - expr.range(), - ))); - } - checker.diagnostics.push(diagnostic); - } - } - CmpOp::Is => { - if check_not_is { - let mut diagnostic = Diagnostic::new(NotIsTest, operand.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - compare(left, &[CmpOp::IsNot], comparators, checker.locator()), - expr.range(), - ))); - } - checker.diagnostics.push(diagnostic); - } - } - _ => {} + } + [CmpOp::Is] => { + if checker.enabled(Rule::NotIsTest) { + let mut diagnostic = Diagnostic::new(NotIsTest, unary_op.operand.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.set_fix(Fix::automatic(Edit::range_replacement( + generate_comparison( + left, + &[CmpOp::IsNot], + comparators, + unary_op.into(), + checker.locator(), + ), + unary_op.range(), + ))); } + checker.diagnostics.push(diagnostic); } } + _ => {} } } diff --git a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs index 59fb21577b448..d0ae2d70a9cf5 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs @@ -1,31 +1,34 @@ -use itertools::izip; -use ruff_python_ast::{self as ast, CmpOp, Constant, Expr, Ranged}; - +use itertools::Itertools; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, CmpOp, Expr, Ranged}; use crate::checkers::ast::Checker; /// ## What it does -/// Checks for object type comparisons without using isinstance(). +/// Checks for object type comparisons without using `isinstance()`. /// /// ## Why is this bad? /// Do not compare types directly. -/// When checking if an object is a instance of a certain type, keep in mind that it might -/// be subclassed. E.g. `bool` inherits from `int` or `Exception` inherits from `BaseException`. +/// +/// When checking if an object is a instance of a certain type, keep in mind +/// that it might be subclassed. For example, `bool` inherits from `int`, and +/// `Exception` inherits from `BaseException`. /// /// ## Example /// ```python /// if type(obj) is type(1): /// pass +/// +/// if type(obj) is int: +/// pass /// ``` /// /// Use instead: /// ```python /// if isinstance(obj, int): /// pass -/// if type(a1) is type(b1): -/// pass /// ``` #[violation] pub struct TypeComparison; @@ -38,57 +41,84 @@ impl Violation for TypeComparison { } /// E721 -pub(crate) fn type_comparison( - checker: &mut Checker, - expr: &Expr, - ops: &[CmpOp], - comparators: &[Expr], -) { - for (op, right) in izip!(ops, comparators) { +pub(crate) fn type_comparison(checker: &mut Checker, compare: &ast::ExprCompare) { + for ((left, right), op) in std::iter::once(compare.left.as_ref()) + .chain(compare.comparators.iter()) + .tuple_windows() + .zip(compare.ops.iter()) + { if !matches!(op, CmpOp::Is | CmpOp::IsNot | CmpOp::Eq | CmpOp::NotEq) { continue; } + + // Left-hand side must be, e.g., `type(obj)`. + let Expr::Call(ast::ExprCall { func, .. }) = left else { + continue; + }; + + let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else { + continue; + }; + + if !(id == "type" && checker.semantic().is_builtin("type")) { + continue; + } + + // Right-hand side must be, e.g., `type(1)` or `int`. match right { - Expr::Call(ast::ExprCall { func, args, .. }) => { - if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { - // Ex) `type(False)` - if id == "type" && checker.semantic().is_builtin("type") { - if let Some(arg) = args.first() { - // Allow comparison for types which are not obvious. - if !matches!( - arg, - Expr::Name(_) - | Expr::Constant(ast::ExprConstant { - value: Constant::None, - kind: None, - range: _ - }) - ) { - checker - .diagnostics - .push(Diagnostic::new(TypeComparison, expr.range())); - } - } - } - } - } - Expr::Attribute(ast::ExprAttribute { value, .. }) => { - if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { - // Ex) `types.NoneType` - if id == "types" - && checker - .semantic() - .resolve_call_path(value) - .map_or(false, |call_path| { - call_path.first().map_or(false, |module| *module == "types") - }) + Expr::Call(ast::ExprCall { + func, arguments, .. + }) => { + // Ex) `type(obj) is type(1)` + let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else { + continue; + }; + + if id == "type" && checker.semantic().is_builtin("type") { + // Allow comparison for types which are not obvious. + if arguments + .args + .first() + .is_some_and(|arg| !arg.is_name_expr() && !is_const_none(arg)) { checker .diagnostics - .push(Diagnostic::new(TypeComparison, expr.range())); + .push(Diagnostic::new(TypeComparison, compare.range())); } } } + Expr::Attribute(ast::ExprAttribute { value, .. }) => { + // Ex) `type(obj) is types.NoneType` + if checker + .semantic() + .resolve_call_path(value.as_ref()) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["types", ..])) + { + checker + .diagnostics + .push(Diagnostic::new(TypeComparison, compare.range())); + } + } + Expr::Name(ast::ExprName { id, .. }) => { + // Ex) `type(obj) is int` + if matches!( + id.as_str(), + "int" + | "str" + | "float" + | "bool" + | "complex" + | "bytes" + | "list" + | "dict" + | "set" + ) && checker.semantic().is_builtin(id) + { + checker + .diagnostics + .push(Diagnostic::new(TypeComparison, compare.range())); + } + } _ => {} } } diff --git a/crates/ruff/src/rules/pycodestyle/settings.rs b/crates/ruff/src/rules/pycodestyle/settings.rs index 7366930d109e4..7d5d2bcb6b710 100644 --- a/crates/ruff/src/rules/pycodestyle/settings.rs +++ b/crates/ruff/src/rules/pycodestyle/settings.rs @@ -20,7 +20,10 @@ pub struct Options { "# )] /// The maximum line length to allow for line-length violations within - /// documentation (`W505`), including standalone comments. + /// documentation (`W505`), including standalone comments. By default, + /// this is set to null which disables reporting violations. + /// + /// See the [`doc-line-too-long`](https://beta.ruff.rs/docs/rules/doc-line-too-long/) rule for more information. pub max_doc_length: Option, #[option( default = "false", diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E231_E23.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E231_E23.py.snap index 34bd1a6274d76..7a197e524746c 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E231_E23.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E231_E23.py.snap @@ -98,5 +98,7 @@ E23.py:29:20: E231 [*] Missing whitespace after ':' 29 |- 'tag_smalldata':[('byte_count_mdtype', 'u4'), ('data', 'S4')], 29 |+ 'tag_smalldata': [('byte_count_mdtype', 'u4'), ('data', 'S4')], 30 30 | } +31 31 | +32 32 | #: Okay diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E402_E402.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E402_E402.py.snap index f768015c97841..a0518e1437172 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E402_E402.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E402_E402.py.snap @@ -9,4 +9,20 @@ E402.py:24:1: E402 Module level import not at top of file | ^^^^^^^^ E402 | +E402.py:34:1: E402 Module level import not at top of file + | +32 | import g +33 | +34 | import h; import i + | ^^^^^^^^ E402 + | + +E402.py:34:11: E402 Module level import not at top of file + | +32 | import g +33 | +34 | import h; import i + | ^^^^^^^^ E402 + | + diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E712_E712.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E712_E712.py.snap index e2a9be7b88be8..ba3f1143bd887 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E712_E712.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E712_E712.py.snap @@ -181,7 +181,7 @@ E712.py:22:5: E712 [*] Comparison to `True` should be `cond is True` or `if cond 20 20 | var = 1 if cond == True else -1 if cond == False else cond 21 21 | #: E712 22 |-if (True) == TrueElement or x == TrueElement: - 22 |+if True is TrueElement or x == TrueElement: + 22 |+if (True) is TrueElement or x == TrueElement: 23 23 | pass 24 24 | 25 25 | if res == True != False: @@ -204,7 +204,7 @@ E712.py:25:11: E712 [*] Comparison to `True` should be `cond is True` or `if con 25 |+if res is True is not False: 26 26 | pass 27 27 | -28 28 | #: Okay +28 28 | if(True) == TrueElement or x == TrueElement: E712.py:25:19: E712 [*] Comparison to `False` should be `cond is not False` or `if cond:` | @@ -224,6 +224,46 @@ E712.py:25:19: E712 [*] Comparison to `False` should be `cond is not False` or ` 25 |+if res is True is not False: 26 26 | pass 27 27 | -28 28 | #: Okay +28 28 | if(True) == TrueElement or x == TrueElement: + +E712.py:28:4: E712 [*] Comparison to `True` should be `cond is True` or `if cond:` + | +26 | pass +27 | +28 | if(True) == TrueElement or x == TrueElement: + | ^^^^ E712 +29 | pass + | + = help: Replace with `cond is True` + +ℹ Suggested fix +25 25 | if res == True != False: +26 26 | pass +27 27 | +28 |-if(True) == TrueElement or x == TrueElement: + 28 |+if(True) is TrueElement or x == TrueElement: +29 29 | pass +30 30 | +31 31 | if (yield i) == True: + +E712.py:31:17: E712 [*] Comparison to `True` should be `cond is True` or `if cond:` + | +29 | pass +30 | +31 | if (yield i) == True: + | ^^^^ E712 +32 | print("even") + | + = help: Replace with `cond is True` + +ℹ Suggested fix +28 28 | if(True) == TrueElement or x == TrueElement: +29 29 | pass +30 30 | +31 |-if (yield i) == True: + 31 |+if (yield i) is True: +32 32 | print("even") +33 33 | +34 34 | #: Okay diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E721_E721.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E721_E721.py.snap index 764b9511eb9cb..50476a509094a 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E721_E721.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E721_E721.py.snap @@ -20,16 +20,6 @@ E721.py:5:4: E721 Do not compare types, use `isinstance()` 7 | #: E721 | -E721.py:10:4: E721 Do not compare types, use `isinstance()` - | - 8 | import types - 9 | -10 | if res == types.IntType: - | ^^^^^^^^^^^^^^^^^^^^ E721 -11 | pass -12 | #: E721 - | - E721.py:15:4: E721 Do not compare types, use `isinstance()` | 13 | import types @@ -155,4 +145,29 @@ E721.py:42:8: E721 Do not compare types, use `isinstance()` 44 | #: Okay | +E721.py:63:8: E721 Do not compare types, use `isinstance()` + | +62 | #: E721 +63 | assert type(res) is int + | ^^^^^^^^^^^^^^^^ E721 + | + +E721.py:69:12: E721 Do not compare types, use `isinstance()` + | +67 | def asdf(self, value: str | None): +68 | #: E721 +69 | if type(value) is str: + | ^^^^^^^^^^^^^^^^^^ E721 +70 | ... + | + +E721.py:79:12: E721 Do not compare types, use `isinstance()` + | +77 | def asdf(self, value: str | None): +78 | #: E721 +79 | if type(value) is str: + | ^^^^^^^^^^^^^^^^^^ E721 +80 | ... + | + diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap index 440cc87ebd689..39603bd0c2bb5 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap @@ -109,7 +109,7 @@ E731.py:57:5: E731 [*] Do not assign a `lambda` expression, use a `def` | = help: Rewrite `f` as a `def` -ℹ Suggested fix +ℹ Possible fix 54 54 | 55 55 | class Scope: 56 56 | # E731 @@ -318,5 +318,43 @@ E731.py:135:5: E731 [*] Do not assign a `lambda` expression, use a `def` 135 |- f: Callable[[str, int, list[str]], list[str]] = lambda a, b, /, c: [*c, a * b] 135 |+ def f(a: str, b: int, /, c: list[str]) -> list[str]: 136 |+ return [*c, a * b] +136 137 | +137 138 | +138 139 | class TemperatureScales(Enum): + +E731.py:139:5: E731 [*] Do not assign a `lambda` expression, use a `def` + | +138 | class TemperatureScales(Enum): +139 | CELSIUS = (lambda deg_c: deg_c) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E731 +140 | FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32) + | + = help: Rewrite `CELSIUS` as a `def` + +ℹ Possible fix +136 136 | +137 137 | +138 138 | class TemperatureScales(Enum): +139 |- CELSIUS = (lambda deg_c: deg_c) + 139 |+ def CELSIUS(deg_c): + 140 |+ return deg_c +140 141 | FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32) + +E731.py:140:5: E731 [*] Do not assign a `lambda` expression, use a `def` + | +138 | class TemperatureScales(Enum): +139 | CELSIUS = (lambda deg_c: deg_c) +140 | FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E731 + | + = help: Rewrite `FAHRENHEIT` as a `def` + +ℹ Possible fix +137 137 | +138 138 | class TemperatureScales(Enum): +139 139 | CELSIUS = (lambda deg_c: deg_c) +140 |- FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32) + 140 |+ def FAHRENHEIT(deg_c): + 141 |+ return deg_c * 9 / 5 + 32 diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_1.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_1.snap index 46f4bc8f55512..b20cb9ecbf9f5 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_1.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_1.snap @@ -1,56 +1,51 @@ --- source: crates/ruff/src/rules/pycodestyle/mod.rs --- -E501_2.py:1:81: E501 Line too long (89 > 88 characters) +E501_2.py:2:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa + | ^ E501 +3 | # a +4 | # a | -E501_2.py:2:81: E501 Line too long (89 > 88 characters) +E501_2.py:3:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa +3 | # a + | ^ E501 +4 | # a +5 | # aa | -E501_2.py:4:81: E501 Line too long (89 > 88 characters) +E501_2.py:7:7: E501 Line too long (7 > 6 characters) | -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +5 | # aa +6 | # aaa +7 | # aaaa + | ^ E501 +8 | # a +9 | # aa | -E501_2.py:5:81: E501 Line too long (89 > 88 characters) - | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | - -E501_2.py:7:82: E501 Line too long (89 > 88 characters) - | -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | +E501_2.py:10:7: E501 Line too long (7 > 6 characters) + | + 8 | # a + 9 | # aa +10 | # aaa + | ^ E501 +11 | +12 | if True: # noqa: E501 + | -E501_2.py:10:82: E501 Line too long (89 > 88 characters) +E501_2.py:16:7: E501 Line too long (7 > 6 characters) | - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -11 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +14 | [12 ] +15 | [1,2] +16 | [1, 2] + | ^ E501 | diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_2.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_2.snap index 46f4bc8f55512..e2f7159f9c506 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_2.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_2.snap @@ -1,56 +1,90 @@ --- source: crates/ruff/src/rules/pycodestyle/mod.rs --- -E501_2.py:1:81: E501 Line too long (89 > 88 characters) +E501_2.py:2:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa + | ^ E501 +3 | # a +4 | # a | -E501_2.py:2:81: E501 Line too long (89 > 88 characters) +E501_2.py:3:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa +3 | # a + | ^ E501 +4 | # a +5 | # aa | -E501_2.py:4:81: E501 Line too long (89 > 88 characters) +E501_2.py:6:6: E501 Line too long (7 > 6 characters) | -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +4 | # a +5 | # aa +6 | # aaa + | ^ E501 +7 | # aaaa +8 | # a | -E501_2.py:5:81: E501 Line too long (89 > 88 characters) +E501_2.py:7:6: E501 Line too long (8 > 6 characters) | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +5 | # aa +6 | # aaa +7 | # aaaa + | ^^ E501 +8 | # a +9 | # aa | -E501_2.py:7:82: E501 Line too long (89 > 88 characters) - | -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | +E501_2.py:8:5: E501 Line too long (7 > 6 characters) + | + 6 | # aaa + 7 | # aaaa + 8 | # a + | ^ E501 + 9 | # aa +10 | # aaa + | + +E501_2.py:9:5: E501 Line too long (8 > 6 characters) + | + 7 | # aaaa + 8 | # a + 9 | # aa + | ^^ E501 +10 | # aaa + | + +E501_2.py:10:5: E501 Line too long (9 > 6 characters) + | + 8 | # a + 9 | # aa +10 | # aaa + | ^^^ E501 +11 | +12 | if True: # noqa: E501 + | + +E501_2.py:14:6: E501 Line too long (7 > 6 characters) + | +12 | if True: # noqa: E501 +13 | [12] +14 | [12 ] + | ^ E501 +15 | [1,2] +16 | [1, 2] + | -E501_2.py:10:82: E501 Line too long (89 > 88 characters) +E501_2.py:16:6: E501 Line too long (8 > 6 characters) | - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -11 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +14 | [12 ] +15 | [1,2] +16 | [1, 2] + | ^^ E501 | diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_4.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_4.snap index dc40a961540c3..3fd272e5d0398 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_4.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_4.snap @@ -1,65 +1,110 @@ --- source: crates/ruff/src/rules/pycodestyle/mod.rs --- -E501_2.py:1:81: E501 Line too long (89 > 88 characters) +E501_2.py:2:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa + | ^ E501 +3 | # a +4 | # a | -E501_2.py:2:77: E501 Line too long (93 > 88 characters) +E501_2.py:3:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^^^^^ E501 -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa +3 | # a + | ^ E501 +4 | # a +5 | # aa | -E501_2.py:4:81: E501 Line too long (89 > 88 characters) +E501_2.py:4:4: E501 Line too long (7 > 6 characters) | -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +2 | # aaaaa +3 | # a +4 | # a + | ^ E501 +5 | # aa +6 | # aaa | -E501_2.py:5:77: E501 Line too long (93 > 88 characters) +E501_2.py:5:4: E501 Line too long (8 > 6 characters) | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^^^^^ E501 -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +3 | # a +4 | # a +5 | # aa + | ^^ E501 +6 | # aaa +7 | # aaaa | -E501_2.py:7:82: E501 Line too long (89 > 88 characters) +E501_2.py:6:4: E501 Line too long (9 > 6 characters) | -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +4 | # a +5 | # aa +6 | # aaa + | ^^^ E501 +7 | # aaaa +8 | # a | -E501_2.py:8:78: E501 Line too long (89 > 88 characters) +E501_2.py:7:4: E501 Line too long (10 > 6 characters) + | +5 | # aa +6 | # aaa +7 | # aaaa + | ^^^^ E501 +8 | # a +9 | # aa + | + +E501_2.py:8:3: E501 Line too long (11 > 6 characters) + | + 6 | # aaa + 7 | # aaaa + 8 | # a + | ^^^ E501 + 9 | # aa +10 | # aaa + | + +E501_2.py:9:3: E501 Line too long (12 > 6 characters) + | + 7 | # aaaa + 8 | # a + 9 | # aa + | ^^^^ E501 +10 | # aaa + | + +E501_2.py:10:3: E501 Line too long (13 > 6 characters) + | + 8 | # a + 9 | # aa +10 | # aaa + | ^^^^^ E501 +11 | +12 | if True: # noqa: E501 + | + +E501_2.py:14:4: E501 Line too long (9 > 6 characters) | - 7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +12 | if True: # noqa: E501 +13 | [12] +14 | [12 ] + | ^^^ E501 +15 | [1,2] +16 | [1, 2] | -E501_2.py:10:82: E501 Line too long (89 > 88 characters) +E501_2.py:16:4: E501 Line too long (10 > 6 characters) | - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -11 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +14 | [12 ] +15 | [1,2] +16 | [1, 2] + | ^^^^ E501 | diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_8.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_8.snap index bce5eac6e3539..7b2dd3f8f98ab 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_8.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__tab_size_8.snap @@ -1,72 +1,110 @@ --- source: crates/ruff/src/rules/pycodestyle/mod.rs --- -E501_2.py:1:81: E501 Line too long (89 > 88 characters) +E501_2.py:2:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa + | ^ E501 +3 | # a +4 | # a | -E501_2.py:2:70: E501 Line too long (101 > 88 characters) +E501_2.py:3:7: E501 Line too long (7 > 6 characters) | -1 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^^^^^^^^^^^^^ E501 -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +1 | # aaaa +2 | # aaaaa +3 | # a + | ^ E501 +4 | # a +5 | # aa | -E501_2.py:4:81: E501 Line too long (89 > 88 characters) +E501_2.py:4:2: E501 Line too long (11 > 6 characters) | -2 | a = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -3 | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +2 | # aaaaa +3 | # a +4 | # a + | ^^^ E501 +5 | # aa +6 | # aaa | -E501_2.py:5:70: E501 Line too long (101 > 88 characters) +E501_2.py:5:2: E501 Line too long (12 > 6 characters) | -4 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^^^^^^^^^^^^^ E501 -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +3 | # a +4 | # a +5 | # aa + | ^^^^ E501 +6 | # aaa +7 | # aaaa | -E501_2.py:7:82: E501 Line too long (89 > 88 characters) +E501_2.py:6:2: E501 Line too long (13 > 6 characters) | -5 | b = """ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -6 | -7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +4 | # a +5 | # aa +6 | # aaa + | ^^^^^ E501 +7 | # aaaa +8 | # a | -E501_2.py:8:71: E501 Line too long (97 > 88 characters) +E501_2.py:7:2: E501 Line too long (14 > 6 characters) + | +5 | # aa +6 | # aaa +7 | # aaaa + | ^^^^^^ E501 +8 | # a +9 | # aa + | + +E501_2.py:8:2: E501 Line too long (19 > 6 characters) + | + 6 | # aaa + 7 | # aaaa + 8 | # a + | ^^^^^^^ E501 + 9 | # aa +10 | # aaa + | + +E501_2.py:9:2: E501 Line too long (20 > 6 characters) + | + 7 | # aaaa + 8 | # a + 9 | # aa + | ^^^^^^^^ E501 +10 | # aaa + | + +E501_2.py:10:2: E501 Line too long (21 > 6 characters) | - 7 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^^^^^^^^ E501 - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" + 8 | # a + 9 | # aa +10 | # aaa + | ^^^^^^^^^ E501 +11 | +12 | if True: # noqa: E501 | -E501_2.py:10:82: E501 Line too long (89 > 88 characters) +E501_2.py:14:2: E501 Line too long (13 > 6 characters) | - 8 | c = """2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - 9 | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 -11 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" +12 | if True: # noqa: E501 +13 | [12] +14 | [12 ] + | ^^^^^ E501 +15 | [1,2] +16 | [1, 2] | -E501_2.py:11:70: E501 Line too long (89 > 88 characters) +E501_2.py:16:2: E501 Line too long (14 > 6 characters) | -10 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" -11 | d = """💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A67ß9💣2ℝ4A6""" - | ^ E501 +14 | [12 ] +15 | [1,2] +16 | [1, 2] + | ^^^^^^ E501 | diff --git a/crates/ruff/src/rules/pydocstyle/helpers.rs b/crates/ruff/src/rules/pydocstyle/helpers.rs index 17aab82f78510..c582bb1742778 100644 --- a/crates/ruff/src/rules/pydocstyle/helpers.rs +++ b/crates/ruff/src/rules/pydocstyle/helpers.rs @@ -1,10 +1,9 @@ use std::collections::BTreeSet; use ruff_python_ast::call_path::from_qualified_name; -use ruff_python_ast::cast; use ruff_python_ast::helpers::map_callable; -use ruff_python_ast::str::is_implicit_concatenation; -use ruff_python_semantic::{Definition, Member, MemberKind, SemanticModel}; +use ruff_python_ast::Expr; +use ruff_python_semantic::{Definition, SemanticModel}; use ruff_source_file::UniversalNewlines; /// Return the index of the first logical line in a string. @@ -48,31 +47,27 @@ pub(crate) fn should_ignore_definition( return false; } - if let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = definition - { - for decorator in cast::decorator_list(stmt) { - if let Some(call_path) = semantic.resolve_call_path(map_callable(&decorator.expression)) - { - if ignore_decorators + let Some(function) = definition.as_function_def() else { + return false; + }; + + function.decorator_list.iter().any(|decorator| { + semantic + .resolve_call_path(map_callable(&decorator.expression)) + .is_some_and(|call_path| { + ignore_decorators .iter() .any(|decorator| from_qualified_name(decorator) == call_path) - { - return true; - } - } - } - } - false + }) + }) } /// Check if a docstring should be ignored. -pub(crate) fn should_ignore_docstring(contents: &str) -> bool { +pub(crate) fn should_ignore_docstring(docstring: &Expr) -> bool { // Avoid analyzing docstrings that contain implicit string concatenations. // Python does consider these docstrings, but they're almost certainly a // user error, and supporting them "properly" is extremely difficult. - is_implicit_concatenation(contents) + docstring + .as_constant_expr() + .is_some_and(|constant| constant.value.is_implicit_concatenated()) } diff --git a/crates/ruff/src/rules/pydocstyle/mod.rs b/crates/ruff/src/rules/pydocstyle/mod.rs index 41c6a1fc6f943..c8a525466665b 100644 --- a/crates/ruff/src/rules/pydocstyle/mod.rs +++ b/crates/ruff/src/rules/pydocstyle/mod.rs @@ -39,6 +39,7 @@ mod tests { #[test_case(Rule::NewLineAfterLastParagraph, Path::new("D.py"))] #[test_case(Rule::NewLineAfterSectionName, Path::new("sections.py"))] #[test_case(Rule::NoBlankLineAfterFunction, Path::new("D.py"))] + #[test_case(Rule::FitsOnOneLine, Path::new("D200.py"))] #[test_case(Rule::NoBlankLineAfterFunction, Path::new("D202.py"))] #[test_case(Rule::BlankLineBeforeClass, Path::new("D.py"))] #[test_case(Rule::NoBlankLineBeforeFunction, Path::new("D.py"))] diff --git a/crates/ruff/src/rules/pydocstyle/rules/backslashes.rs b/crates/ruff/src/rules/pydocstyle/rules/backslashes.rs index 88cbdf2b5818d..508d0dd85ce5d 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/backslashes.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/backslashes.rs @@ -2,6 +2,7 @@ use memchr::memchr_iter; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs index 32bbb59845472..b4d7f4531566a 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_source_file::{UniversalNewlineIterator, UniversalNewlines}; use crate::checkers::ast::Checker; diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs index 77f55b07441ae..3b97c4f80cb28 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_class.rs @@ -1,11 +1,9 @@ -use ruff_python_ast::Ranged; -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Definition, Member, MemberKind}; +use ruff_python_ast::Ranged; use ruff_python_trivia::PythonWhitespace; use ruff_source_file::{UniversalNewlineIterator, UniversalNewlines}; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; @@ -43,9 +41,7 @@ use crate::registry::{AsRule, Rule}; /// /// [D211]: https://beta.ruff.rs/docs/rules/blank-line-before-class #[violation] -pub struct OneBlankLineBeforeClass { - lines: usize, -} +pub struct OneBlankLineBeforeClass; impl AlwaysAutofixableViolation for OneBlankLineBeforeClass { #[derive_message_formats] @@ -97,9 +93,7 @@ impl AlwaysAutofixableViolation for OneBlankLineBeforeClass { /// /// [PEP 257]: https://peps.python.org/pep-0257/ #[violation] -pub struct OneBlankLineAfterClass { - lines: usize, -} +pub struct OneBlankLineAfterClass; impl AlwaysAutofixableViolation for OneBlankLineAfterClass { #[derive_message_formats] @@ -144,9 +138,7 @@ impl AlwaysAutofixableViolation for OneBlankLineAfterClass { /// /// [D203]: https://beta.ruff.rs/docs/rules/one-blank-line-before-class #[violation] -pub struct BlankLineBeforeClass { - lines: usize, -} +pub struct BlankLineBeforeClass; impl AlwaysAutofixableViolation for BlankLineBeforeClass { #[derive_message_formats] @@ -161,23 +153,28 @@ impl AlwaysAutofixableViolation for BlankLineBeforeClass { /// D203, D204, D211 pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) { - let Definition::Member(Member { - kind: MemberKind::Class | MemberKind::NestedClass, - stmt, - .. - }) = docstring.definition - else { + let Some(class) = docstring.definition.as_class_def() else { return; }; + // Special-case: the docstring is on the same line as the class. For example: + // ```python + // class PhotoMetadata: """Metadata about a photo.""" + // ``` + let between_range = TextRange::new(class.start(), docstring.start()); + if !checker.locator().contains_line_break(between_range) { + return; + } + if checker.enabled(Rule::OneBlankLineBeforeClass) || checker.enabled(Rule::BlankLineBeforeClass) { - let before = checker - .locator() - .slice(TextRange::new(stmt.start(), docstring.start())); + let mut lines = UniversalNewlineIterator::with_offset( + checker.locator().slice(between_range), + between_range.start(), + ) + .rev(); let mut blank_lines_before = 0usize; - let mut lines = UniversalNewlineIterator::with_offset(before, stmt.start()).rev(); let mut blank_lines_start = lines.next().map(|line| line.start()).unwrap_or_default(); for line in lines { @@ -191,12 +188,7 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr if checker.enabled(Rule::BlankLineBeforeClass) { if blank_lines_before != 0 { - let mut diagnostic = Diagnostic::new( - BlankLineBeforeClass { - lines: blank_lines_before, - }, - docstring.range(), - ); + let mut diagnostic = Diagnostic::new(BlankLineBeforeClass, docstring.range()); if checker.patch(diagnostic.kind.rule()) { // Delete the blank line before the class. diagnostic.set_fix(Fix::automatic(Edit::deletion( @@ -209,12 +201,7 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr } if checker.enabled(Rule::OneBlankLineBeforeClass) { if blank_lines_before != 1 { - let mut diagnostic = Diagnostic::new( - OneBlankLineBeforeClass { - lines: blank_lines_before, - }, - docstring.range(), - ); + let mut diagnostic = Diagnostic::new(OneBlankLineBeforeClass, docstring.range()); if checker.patch(diagnostic.kind.rule()) { // Insert one blank line before the class. diagnostic.set_fix(Fix::automatic(Edit::replacement( @@ -229,9 +216,9 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr } if checker.enabled(Rule::OneBlankLineAfterClass) { - let after = checker - .locator() - .slice(TextRange::new(docstring.end(), stmt.end())); + let after_range = TextRange::new(docstring.end(), class.end()); + + let after = checker.locator().slice(after_range); let all_blank_after = after.universal_newlines().skip(1).all(|line| { line.trim_whitespace().is_empty() || line.trim_whitespace_start().starts_with('#') @@ -240,9 +227,10 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr return; } - let mut blank_lines_after = 0usize; - let mut lines = UniversalNewlineIterator::with_offset(after, docstring.end()); + let mut lines = UniversalNewlineIterator::with_offset(after, after_range.start()); + let first_line_start = lines.next().map(|l| l.start()).unwrap_or_default(); + let mut blank_lines_after = 0usize; let mut blank_lines_end = docstring.end(); for line in lines { @@ -255,12 +243,7 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr } if blank_lines_after != 1 { - let mut diagnostic = Diagnostic::new( - OneBlankLineAfterClass { - lines: blank_lines_after, - }, - docstring.range(), - ); + let mut diagnostic = Diagnostic::new(OneBlankLineAfterClass, docstring.range()); if checker.patch(diagnostic.kind.rule()) { // Insert a blank line before the class (replacing any existing lines). diagnostic.set_fix(Fix::automatic(Edit::replacement( diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs index a41f64dfebac1..8ae76d05380f0 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_before_after_function.rs @@ -1,13 +1,12 @@ use once_cell::sync::Lazy; use regex::Regex; -use ruff_python_ast::Ranged; -use ruff_text_size::{TextLen, TextRange}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Definition, Member, MemberKind}; +use ruff_python_ast::Ranged; use ruff_python_trivia::PythonWhitespace; use ruff_source_file::{UniversalNewlineIterator, UniversalNewlines}; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; @@ -104,21 +103,16 @@ static INNER_FUNCTION_OR_CLASS_REGEX: Lazy = /// D201, D202 pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring) { - let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = docstring.definition - else { + let Some(function) = docstring.definition.as_function_def() else { return; }; if checker.enabled(Rule::NoBlankLineBeforeFunction) { let before = checker .locator() - .slice(TextRange::new(stmt.start(), docstring.start())); + .slice(TextRange::new(function.start(), docstring.start())); - let mut lines = UniversalNewlineIterator::with_offset(before, stmt.start()).rev(); + let mut lines = UniversalNewlineIterator::with_offset(before, function.start()).rev(); let mut blank_lines_before = 0usize; let mut blank_lines_start = lines.next().map(|l| l.end()).unwrap_or_default(); @@ -152,7 +146,7 @@ pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Doc if checker.enabled(Rule::NoBlankLineAfterFunction) { let after = checker .locator() - .slice(TextRange::new(docstring.end(), stmt.end())); + .slice(TextRange::new(docstring.end(), function.end())); // If the docstring is only followed by blank and commented lines, abort. let all_blank_after = after.universal_newlines().skip(1).all(|line| { @@ -182,7 +176,7 @@ pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Doc if blank_lines_after == 1 && lines .find(|line| !line.trim_whitespace_start().starts_with('#')) - .map_or(false, |line| INNER_FUNCTION_OR_CLASS_REGEX.is_match(&line)) + .is_some_and(|line| INNER_FUNCTION_OR_CLASS_REGEX.is_match(&line)) { return; } diff --git a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs index 918a5d2c326b8..f329672405669 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/capitalized.rs @@ -1,9 +1,7 @@ -use ruff_python_ast::Ranged; -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Definition, Member, MemberKind}; +use ruff_python_ast::Ranged; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; @@ -57,13 +55,7 @@ impl AlwaysAutofixableViolation for FirstLineCapitalized { /// D403 pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) { - if !matches!( - docstring.definition, - Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - .. - }) - ) { + if docstring.definition.as_function_def().is_none() { return; } diff --git a/crates/ruff/src/rules/pydocstyle/rules/ends_with_period.rs b/crates/ruff/src/rules/pydocstyle/rules/ends_with_period.rs index 0fb03df11a476..7d16b5bcce52e 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/ends_with_period.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/ends_with_period.rs @@ -3,6 +3,7 @@ use strum::IntoEnumIterator; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_source_file::{UniversalNewlineIterator, UniversalNewlines}; use crate::checkers::ast::Checker; diff --git a/crates/ruff/src/rules/pydocstyle/rules/ends_with_punctuation.rs b/crates/ruff/src/rules/pydocstyle/rules/ends_with_punctuation.rs index 5649479de27ca..aa06dafc5f87b 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/ends_with_punctuation.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/ends_with_punctuation.rs @@ -3,6 +3,7 @@ use strum::IntoEnumIterator; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_source_file::{UniversalNewlineIterator, UniversalNewlines}; use crate::checkers::ast::Checker; diff --git a/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs b/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs index ee9e2364eafee..e4880a609d0bf 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs @@ -1,9 +1,7 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::cast; use ruff_python_ast::identifier::Identifier; use ruff_python_semantic::analyze::visibility::is_overload; -use ruff_python_semantic::{Definition, Member, MemberKind}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; @@ -80,18 +78,13 @@ impl Violation for OverloadWithDocstring { /// D418 pub(crate) fn if_needed(checker: &mut Checker, docstring: &Docstring) { - let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = docstring.definition - else { + let Some(function) = docstring.definition.as_function_def() else { return; }; - if !is_overload(cast::decorator_list(stmt), checker.semantic()) { - return; + if is_overload(&function.decorator_list, checker.semantic()) { + checker.diagnostics.push(Diagnostic::new( + OverloadWithDocstring, + function.identifier(), + )); } - checker - .diagnostics - .push(Diagnostic::new(OverloadWithDocstring, stmt.identifier())); } diff --git a/crates/ruff/src/rules/pydocstyle/rules/indent.rs b/crates/ruff/src/rules/pydocstyle/rules/indent.rs index f97bdf88b0473..663ee9cae3fde 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/indent.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/indent.rs @@ -1,10 +1,10 @@ -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::docstrings::{clean_space, leading_space}; +use ruff_python_ast::Ranged; use ruff_source_file::NewlineWithTrailingNewline; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs b/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs index 46d3f6eed3a33..1d58abeb56cb8 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/multi_line_summary_start.rs @@ -4,7 +4,7 @@ use ruff_text_size::{TextRange, TextSize}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::str::{is_triple_quote, leading_quote}; -use ruff_python_semantic::{Definition, Member}; +use ruff_python_semantic::Definition; use ruff_source_file::{NewlineWithTrailingNewline, UniversalNewlineIterator}; use crate::checkers::ast::Checker; @@ -164,11 +164,11 @@ pub(crate) fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstr // If the docstring isn't on its own line, look at the statement indentation, // and add the default indentation to get the "right" level. - if let Definition::Member(Member { stmt, .. }) = &docstring.definition { - let stmt_line_start = checker.locator().line_start(stmt.start()); + if let Definition::Member(member) = &docstring.definition { + let stmt_line_start = checker.locator().line_start(member.start()); let stmt_indentation = checker .locator() - .slice(TextRange::new(stmt_line_start, stmt.start())); + .slice(TextRange::new(stmt_line_start, member.start())); if stmt_indentation.chars().all(char::is_whitespace) { indentation.clear(); diff --git a/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs b/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs index 07ff14f11491b..5ba744a56b6de 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/no_signature.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{self as ast, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Definition, Member, MemberKind}; +use ruff_python_ast::Ranged; use ruff_source_file::UniversalNewlines; use crate::checkers::ast::Checker; @@ -54,15 +52,7 @@ impl Violation for NoSignature { /// D402 pub(crate) fn no_signature(checker: &mut Checker, docstring: &Docstring) { - let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = docstring.definition - else { - return; - }; - let Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) = stmt else { + let Some(function) = docstring.definition.as_function_def() else { return; }; @@ -72,11 +62,14 @@ pub(crate) fn no_signature(checker: &mut Checker, docstring: &Docstring) { return; }; - if !first_line.contains(&format!("{name}(")) { - return; - }; - - checker - .diagnostics - .push(Diagnostic::new(NoSignature, docstring.range())); + // Search for occurrences of the function name followed by an open parenthesis (e.g., `foo(` for + // a function named `foo`). + if first_line + .match_indices(function.name.as_str()) + .any(|(index, _)| first_line[index + function.name.len()..].starts_with('(')) + { + checker + .diagnostics + .push(Diagnostic::new(NoSignature, docstring.range())); + } } diff --git a/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs b/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs index cf01e3fee8351..d2a30fee7119c 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs @@ -1,8 +1,8 @@ -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_source_file::NewlineWithTrailingNewline; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs b/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs index 39d72e7dbacde..fc61f13a6dc09 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs @@ -6,9 +6,8 @@ use once_cell::sync::Lazy; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::{from_qualified_name, CallPath}; -use ruff_python_ast::cast; +use ruff_python_ast::Ranged; use ruff_python_semantic::analyze::visibility::{is_property, is_test}; -use ruff_python_semantic::{Definition, Member, MemberKind}; use ruff_source_file::UniversalNewlines; use crate::checkers::ast::Checker; @@ -69,25 +68,18 @@ pub(crate) fn non_imperative_mood( docstring: &Docstring, property_decorators: &BTreeSet, ) { - let Definition::Member(Member { kind, stmt, .. }) = &docstring.definition else { + let Some(function) = docstring.definition.as_function_def() else { return; }; - if !matches!( - kind, - MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - ) { - return; - } - let property_decorators = property_decorators .iter() .map(|decorator| from_qualified_name(decorator)) .collect::>(); - if is_test(cast::name(stmt)) + if is_test(&function.name) || is_property( - cast::decorator_list(stmt), + &function.decorator_list, &property_decorators, checker.semantic(), ) diff --git a/crates/ruff/src/rules/pydocstyle/rules/not_empty.rs b/crates/ruff/src/rules/pydocstyle/rules/not_empty.rs index 3c89974b37133..c8b893fe173b8 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/not_empty.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/not_empty.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs index cefee351cb146..9288f3ff3731b 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs @@ -1,13 +1,11 @@ -use ruff_text_size::TextRange; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::cast; use ruff_python_ast::identifier::Identifier; use ruff_python_semantic::analyze::visibility::{ is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility, }; use ruff_python_semantic::{Definition, Member, MemberKind, Module, ModuleKind}; +use ruff_text_size::TextRange; use crate::checkers::ast::Checker; use crate::registry::Rule; @@ -523,6 +521,10 @@ pub(crate) fn not_missing( definition: &Definition, visibility: Visibility, ) -> bool { + if checker.source_type.is_stub() { + return true; + } + if visibility.is_private() { return true; } @@ -553,82 +555,82 @@ pub(crate) fn not_missing( false } Definition::Member(Member { - kind: MemberKind::Class, - stmt, + kind: MemberKind::Class(class), .. }) => { if checker.enabled(Rule::UndocumentedPublicClass) { checker .diagnostics - .push(Diagnostic::new(UndocumentedPublicClass, stmt.identifier())); + .push(Diagnostic::new(UndocumentedPublicClass, class.identifier())); } false } Definition::Member(Member { - kind: MemberKind::NestedClass, - stmt, + kind: MemberKind::NestedClass(function), .. }) => { if checker.enabled(Rule::UndocumentedPublicNestedClass) { checker.diagnostics.push(Diagnostic::new( UndocumentedPublicNestedClass, - stmt.identifier(), + function.identifier(), )); } false } Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction, - stmt, + kind: MemberKind::Function(function) | MemberKind::NestedFunction(function), .. }) => { - if is_overload(cast::decorator_list(stmt), checker.semantic()) { + if is_overload(&function.decorator_list, checker.semantic()) { true } else { if checker.enabled(Rule::UndocumentedPublicFunction) { checker.diagnostics.push(Diagnostic::new( UndocumentedPublicFunction, - stmt.identifier(), + function.identifier(), )); } false } } Definition::Member(Member { - kind: MemberKind::Method, - stmt, + kind: MemberKind::Method(function), .. }) => { - if is_overload(cast::decorator_list(stmt), checker.semantic()) - || is_override(cast::decorator_list(stmt), checker.semantic()) + if is_overload(&function.decorator_list, checker.semantic()) + || is_override(&function.decorator_list, checker.semantic()) { true - } else if is_init(cast::name(stmt)) { + } else if is_init(&function.name) { if checker.enabled(Rule::UndocumentedPublicInit) { - checker - .diagnostics - .push(Diagnostic::new(UndocumentedPublicInit, stmt.identifier())); + checker.diagnostics.push(Diagnostic::new( + UndocumentedPublicInit, + function.identifier(), + )); } true - } else if is_new(cast::name(stmt)) || is_call(cast::name(stmt)) { + } else if is_new(&function.name) || is_call(&function.name) { if checker.enabled(Rule::UndocumentedPublicMethod) { - checker - .diagnostics - .push(Diagnostic::new(UndocumentedPublicMethod, stmt.identifier())); + checker.diagnostics.push(Diagnostic::new( + UndocumentedPublicMethod, + function.identifier(), + )); } true - } else if is_magic(cast::name(stmt)) { + } else if is_magic(&function.name) { if checker.enabled(Rule::UndocumentedMagicMethod) { - checker - .diagnostics - .push(Diagnostic::new(UndocumentedMagicMethod, stmt.identifier())); + checker.diagnostics.push(Diagnostic::new( + UndocumentedMagicMethod, + function.identifier(), + )); } true } else { if checker.enabled(Rule::UndocumentedPublicMethod) { - checker - .diagnostics - .push(Diagnostic::new(UndocumentedPublicMethod, stmt.identifier())); + checker.diagnostics.push(Diagnostic::new( + UndocumentedPublicMethod, + function.identifier(), + )); } true } diff --git a/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs b/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs index 560f3ab0e114e..97d79244ed271 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs @@ -1,6 +1,7 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::str::{leading_quote, trailing_quote}; +use ruff_python_ast::Ranged; use ruff_source_file::NewlineWithTrailingNewline; use crate::checkers::ast::Checker; @@ -73,7 +74,8 @@ pub(crate) fn one_liner(checker: &mut Checker, docstring: &Docstring) { // characters, avoid applying the fix. let body = docstring.body(); let trimmed = body.trim(); - if !trimmed.ends_with(trailing.chars().last().unwrap()) + if trimmed.chars().rev().take_while(|c| *c == '\\').count() % 2 == 0 + && !trimmed.ends_with(trailing.chars().last().unwrap()) && !trimmed.starts_with(leading.chars().last().unwrap()) { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diff --git a/crates/ruff/src/rules/pydocstyle/rules/sections.rs b/crates/ruff/src/rules/pydocstyle/rules/sections.rs index 99aaeb55d0ab8..44da66e7076f9 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/sections.rs @@ -1,20 +1,18 @@ use itertools::Itertools; use once_cell::sync::Lazy; use regex::Regex; -use ruff_python_ast::{self as ast, ArgWithDefault, Stmt}; -use ruff_text_size::{TextLen, TextRange, TextSize}; use rustc_hash::FxHashSet; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::cast; use ruff_python_ast::docstrings::{clean_space, leading_space}; use ruff_python_ast::identifier::Identifier; +use ruff_python_ast::{ParameterWithDefault, Ranged}; use ruff_python_semantic::analyze::visibility::is_staticmethod; -use ruff_python_semantic::{Definition, Member, MemberKind}; use ruff_python_trivia::{textwrap::dedent, PythonWhitespace}; use ruff_source_file::NewlineWithTrailingNewline; +use ruff_text_size::{TextLen, TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::docstrings::sections::{SectionContext, SectionContexts, SectionKind}; @@ -1642,7 +1640,7 @@ fn common_section( if checker.patch(diagnostic.kind.rule()) { // Replace the existing indentation with whitespace of the appropriate length. let content = clean_space(docstring.indentation); - let fix_range = TextRange::at(context.range().start(), leading_space.text_len()); + let fix_range = TextRange::at(context.start(), leading_space.text_len()); diagnostic.set_fix(Fix::automatic(if content.is_empty() { Edit::range_deletion(fix_range) @@ -1669,7 +1667,7 @@ fn common_section( // Add a newline at the beginning of the next section. diagnostic.set_fix(Fix::automatic(Edit::insertion( line_end.to_string(), - next.range().start(), + next.start(), ))); } checker.diagnostics.push(diagnostic); @@ -1686,7 +1684,7 @@ fn common_section( // Add a newline after the section. diagnostic.set_fix(Fix::automatic(Edit::insertion( format!("{}{}", line_end, docstring.indentation), - context.range().end(), + context.end(), ))); } checker.diagnostics.push(diagnostic); @@ -1695,7 +1693,7 @@ fn common_section( } if checker.enabled(Rule::NoBlankLineBeforeSection) { - if !context.previous_line().map_or(false, str::is_empty) { + if !context.previous_line().is_some_and(str::is_empty) { let mut diagnostic = Diagnostic::new( NoBlankLineBeforeSection { name: context.section_name().to_string(), @@ -1706,7 +1704,7 @@ fn common_section( // Add a blank line before the section. diagnostic.set_fix(Fix::automatic(Edit::insertion( line_end.to_string(), - context.range().start(), + context.start(), ))); } checker.diagnostics.push(diagnostic); @@ -1717,45 +1715,31 @@ fn common_section( } fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &FxHashSet) { - let Definition::Member(Member { - kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method, - stmt, - .. - }) = docstring.definition - else { - return; - }; - - let (Stmt::FunctionDef(ast::StmtFunctionDef { - args: arguments, .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - args: arguments, .. - })) = stmt - else { + let Some(function) = docstring.definition.as_function_def() else { return; }; // Look for arguments that weren't included in the docstring. let mut missing_arg_names: FxHashSet = FxHashSet::default(); - for ArgWithDefault { - def, + for ParameterWithDefault { + parameter, default: _, range: _, - } in arguments + } in function + .parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(&function.parameters.args) + .chain(&function.parameters.kwonlyargs) .skip( // If this is a non-static method, skip `cls` or `self`. usize::from( docstring.definition.is_method() - && !is_staticmethod(cast::decorator_list(stmt), checker.semantic()), + && !is_staticmethod(&function.decorator_list, checker.semantic()), ), ) { - let arg_name = def.arg.as_str(); + let arg_name = parameter.name.as_str(); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) { missing_arg_names.insert(arg_name.to_string()); } @@ -1763,8 +1747,8 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & // Check specifically for `vararg` and `kwarg`, which can be prefixed with a // single or double star, respectively. - if let Some(arg) = &arguments.vararg { - let arg_name = arg.arg.as_str(); + if let Some(arg) = function.parameters.vararg.as_ref() { + let arg_name = arg.name.as_str(); let starred_arg_name = format!("*{arg_name}"); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) @@ -1773,8 +1757,8 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & missing_arg_names.insert(starred_arg_name); } } - if let Some(arg) = &arguments.kwarg { - let arg_name = arg.arg.as_str(); + if let Some(arg) = function.parameters.kwarg.as_ref() { + let arg_name = arg.name.as_str(); let starred_arg_name = format!("**{arg_name}"); if !arg_name.starts_with('_') && !docstrings_args.contains(arg_name) @@ -1792,7 +1776,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & definition: definition.to_string(), names, }, - stmt.identifier(), + function.identifier(), )); } } diff --git a/crates/ruff/src/rules/pydocstyle/rules/starts_with_this.rs b/crates/ruff/src/rules/pydocstyle/rules/starts_with_this.rs index 4e73aa0ed3937..f5f36da599f2a 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/starts_with_this.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/starts_with_this.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; diff --git a/crates/ruff/src/rules/pydocstyle/rules/triple_quotes.rs b/crates/ruff/src/rules/pydocstyle/rules/triple_quotes.rs index 1f054c628c0b0..28a8604393059 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/triple_quotes.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/triple_quotes.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_codegen::Quote; use crate::checkers::ast::Checker; diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D200.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D200.py.snap new file mode 100644 index 0000000000000..d81013659998b --- /dev/null +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D200.py.snap @@ -0,0 +1,45 @@ +--- +source: crates/ruff/src/rules/pydocstyle/mod.rs +--- +D200.py:2:5: D200 One-line docstring should fit on one line + | +1 | def func(): +2 | """\ + | _____^ +3 | | """ + | |_______^ D200 + | + = help: Reformat to one line + +D200.py:7:5: D200 [*] One-line docstring should fit on one line + | +6 | def func(): +7 | """\\ + | _____^ +8 | | """ + | |_______^ D200 + | + = help: Reformat to one line + +ℹ Suggested fix +4 4 | +5 5 | +6 6 | def func(): +7 |- """\\ +8 |- """ + 7 |+ """\\""" +9 8 | +10 9 | +11 10 | def func(): + +D200.py:12:5: D200 One-line docstring should fit on one line + | +11 | def func(): +12 | """\ \ + | _____^ +13 | | """ + | |_______^ D200 + | + = help: Reformat to one line + + diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap index 144c7cb86d5dd..3b92b97fd1edd 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap @@ -272,4 +272,38 @@ D.py:615:5: D400 [*] First line should end with a period 617 617 | """ 618 618 | +D.py:639:17: D400 [*] First line should end with a period + | +639 | class SameLine: """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D400 +640 | +641 | def same_line(): """This is a docstring on the same line""" + | + = help: Add period + +ℹ Suggested fix +636 636 | """ This is a docstring that starts with a space.""" # noqa: D210 +637 637 | +638 638 | +639 |-class SameLine: """This is a docstring on the same line""" + 639 |+class SameLine: """This is a docstring on the same line.""" +640 640 | +641 641 | def same_line(): """This is a docstring on the same line""" + +D.py:641:18: D400 [*] First line should end with a period + | +639 | class SameLine: """This is a docstring on the same line""" +640 | +641 | def same_line(): """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D400 + | + = help: Add period + +ℹ Suggested fix +638 638 | +639 639 | class SameLine: """This is a docstring on the same line""" +640 640 | +641 |-def same_line(): """This is a docstring on the same line""" + 641 |+def same_line(): """This is a docstring on the same line.""" + diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D404_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D404_D.py.snap index 009f74f62a2cb..d372af4445f1e 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D404_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D404_D.py.snap @@ -17,4 +17,20 @@ D.py:636:5: D404 First word of the docstring should not be "This" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D404 | +D.py:639:17: D404 First word of the docstring should not be "This" + | +639 | class SameLine: """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D404 +640 | +641 | def same_line(): """This is a docstring on the same line""" + | + +D.py:641:18: D404 First word of the docstring should not be "This" + | +639 | class SameLine: """This is a docstring on the same line""" +640 | +641 | def same_line(): """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D404 + | + diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap index 2b457967e8b28..73725b09cf181 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap @@ -254,4 +254,38 @@ D.py:615:5: D415 [*] First line should end with a period, question mark, or excl 617 617 | """ 618 618 | +D.py:639:17: D415 [*] First line should end with a period, question mark, or exclamation point + | +639 | class SameLine: """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D415 +640 | +641 | def same_line(): """This is a docstring on the same line""" + | + = help: Add closing punctuation + +ℹ Suggested fix +636 636 | """ This is a docstring that starts with a space.""" # noqa: D210 +637 637 | +638 638 | +639 |-class SameLine: """This is a docstring on the same line""" + 639 |+class SameLine: """This is a docstring on the same line.""" +640 640 | +641 641 | def same_line(): """This is a docstring on the same line""" + +D.py:641:18: D415 [*] First line should end with a period, question mark, or exclamation point + | +639 | class SameLine: """This is a docstring on the same line""" +640 | +641 | def same_line(): """This is a docstring on the same line""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D415 + | + = help: Add closing punctuation + +ℹ Suggested fix +638 638 | +639 639 | class SameLine: """This is a docstring on the same line""" +640 640 | +641 |-def same_line(): """This is a docstring on the same line""" + 641 |+def same_line(): """This is a docstring on the same line.""" + diff --git a/crates/ruff/src/rules/pyflakes/fixes.rs b/crates/ruff/src/rules/pyflakes/fixes.rs index 59d8c1491038f..9a1aa46fb498c 100644 --- a/crates/ruff/src/rules/pyflakes/fixes.rs +++ b/crates/ruff/src/rules/pyflakes/fixes.rs @@ -1,93 +1,88 @@ use anyhow::{Context, Ok, Result}; -use ruff_python_ast::{Expr, Ranged}; -use ruff_text_size::TextRange; use ruff_diagnostics::Edit; +use ruff_python_ast::{self as ast, Ranged}; use ruff_python_codegen::Stylist; use ruff_python_semantic::Binding; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_source_file::Locator; -use crate::autofix::codemods::CodegenStylist; -use crate::cst::matchers::{match_call_mut, match_dict, match_expression}; +use crate::cst::matchers::{match_call_mut, match_dict, transform_expression}; /// Generate a [`Edit`] to remove unused keys from format dict. pub(super) fn remove_unused_format_arguments_from_dict( unused_arguments: &[usize], - stmt: &Expr, + dict: &ast::ExprDict, locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(stmt.range()); - let mut tree = match_expression(module_text)?; - let dict = match_dict(&mut tree)?; - - // Remove the elements at the given indexes. - let mut index = 0; - dict.elements.retain(|_| { - let is_unused = unused_arguments.contains(&index); - index += 1; - !is_unused - }); - - Ok(Edit::range_replacement( - tree.codegen_stylist(stylist), - stmt.range(), - )) + let source_code = locator.slice(dict.range()); + transform_expression(source_code, stylist, |mut expression| { + let dict = match_dict(&mut expression)?; + + // Remove the elements at the given indexes. + let mut index = 0; + dict.elements.retain(|_| { + let is_unused = unused_arguments.contains(&index); + index += 1; + !is_unused + }); + + Ok(expression) + }) + .map(|output| Edit::range_replacement(output, dict.range())) } /// Generate a [`Edit`] to remove unused keyword arguments from a `format` call. pub(super) fn remove_unused_keyword_arguments_from_format_call( unused_arguments: &[usize], - location: TextRange, + call: &ast::ExprCall, locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(location); - let mut tree = match_expression(module_text)?; - let call = match_call_mut(&mut tree)?; - - // Remove the keyword arguments at the given indexes. - let mut index = 0; - call.args.retain(|arg| { - if arg.keyword.is_none() { - return true; - } - - let is_unused = unused_arguments.contains(&index); - index += 1; - !is_unused - }); - - Ok(Edit::range_replacement( - tree.codegen_stylist(stylist), - location, - )) + let source_code = locator.slice(call.range()); + transform_expression(source_code, stylist, |mut expression| { + let call = match_call_mut(&mut expression)?; + + // Remove the keyword arguments at the given indexes. + let mut index = 0; + call.args.retain(|arg| { + if arg.keyword.is_none() { + return true; + } + + let is_unused = unused_arguments.contains(&index); + index += 1; + !is_unused + }); + + Ok(expression) + }) + .map(|output| Edit::range_replacement(output, call.range())) } /// Generate a [`Edit`] to remove unused positional arguments from a `format` call. pub(crate) fn remove_unused_positional_arguments_from_format_call( unused_arguments: &[usize], - location: TextRange, + call: &ast::ExprCall, locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(location); - let mut tree = match_expression(module_text)?; - let call = match_call_mut(&mut tree)?; - - // Remove any unused arguments. - let mut index = 0; - call.args.retain(|_| { - let is_unused = unused_arguments.contains(&index); - index += 1; - !is_unused - }); - - Ok(Edit::range_replacement( - tree.codegen_stylist(stylist), - location, - )) + let source_code = locator.slice(call.range()); + transform_expression(source_code, stylist, |mut expression| { + let call = match_call_mut(&mut expression)?; + + // Remove any unused arguments. + let mut index = 0; + call.args.retain(|_| { + let is_unused = unused_arguments.contains(&index); + index += 1; + !is_unused + }); + + Ok(expression) + }) + .map(|output| Edit::range_replacement(output, call.range())) } /// Generate a [`Edit`] to remove the binding from an exception handler. @@ -96,11 +91,9 @@ pub(crate) fn remove_exception_handler_assignment( locator: &Locator, ) -> Result { // Lex backwards, to the token just before the `as`. - let mut tokenizer = SimpleTokenizer::up_to_without_back_comment( - bound_exception.range.start(), - locator.contents(), - ) - .skip_trivia(); + let mut tokenizer = + SimpleTokenizer::up_to_without_back_comment(bound_exception.start(), locator.contents()) + .skip_trivia(); // Eat the `as` token. let preceding = tokenizer @@ -114,7 +107,7 @@ pub(crate) fn remove_exception_handler_assignment( .context("expected the exception name to be preceded by a token")?; // Lex forwards, to the `:` token. - let following = SimpleTokenizer::starts_at(bound_exception.range.end(), locator.contents()) + let following = SimpleTokenizer::starts_at(bound_exception.end(), locator.contents()) .skip_trivia() .next() .context("expected the exception name to be followed by a colon")?; diff --git a/crates/ruff/src/rules/pyflakes/format.rs b/crates/ruff/src/rules/pyflakes/format.rs index 101a51a6c52e9..bdedd04398075 100644 --- a/crates/ruff/src/rules/pyflakes/format.rs +++ b/crates/ruff/src/rules/pyflakes/format.rs @@ -11,7 +11,9 @@ pub(crate) fn error_to_string(err: &FormatParseError) -> String { FormatParseError::InvalidCharacterAfterRightBracket => { "Only '.' or '[' may follow ']' in format field specifier" } - FormatParseError::InvalidFormatSpecifier => "Max string recursion exceeded", + FormatParseError::PlaceholderRecursionExceeded => { + "Max format placeholder recursion exceeded" + } FormatParseError::MissingStartBracket => "Single '}' encountered in format string", FormatParseError::MissingRightBracket => "Expected '}' before end of string", FormatParseError::UnmatchedBracket => "Single '{' encountered in format string", diff --git a/crates/ruff/src/rules/pyflakes/mod.rs b/crates/ruff/src/rules/pyflakes/mod.rs index 7eb0434f31ef6..ea7288d5a6921 100644 --- a/crates/ruff/src/rules/pyflakes/mod.rs +++ b/crates/ruff/src/rules/pyflakes/mod.rs @@ -12,11 +12,14 @@ mod tests { use anyhow::Result; use regex::Regex; use ruff_python_parser::lexer::LexResult; + use test_case::test_case; use ruff_diagnostics::Diagnostic; + use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; + use ruff_python_parser::AsMode; use ruff_python_trivia::textwrap::dedent; use ruff_source_file::Locator; @@ -504,8 +507,9 @@ mod tests { /// Note that all tests marked with `#[ignore]` should be considered TODOs. fn flakes(contents: &str, expected: &[Rule]) { let contents = dedent(contents); + let source_type = PySourceType::default(); let settings = Settings::for_rules(Linter::Pyflakes.rules()); - let tokens: Vec = ruff_python_parser::tokenize(&contents); + let tokens: Vec = ruff_python_parser::tokenize(&contents, source_type.as_mode()); let locator = Locator::new(&contents); let stylist = Stylist::from_tokens(&tokens, &locator); let indexer = Indexer::from_tokens(&tokens, &locator); @@ -529,6 +533,7 @@ mod tests { &settings, flags::Noqa::Enabled, None, + source_type, ); diagnostics.sort_by_key(Diagnostic::start); let actual = diagnostics @@ -3422,7 +3427,7 @@ mod tests { } #[test] - fn type_alias_annotations() { + fn use_pep695_type_aliass() { flakes( r#" from typing_extensions import TypeAlias diff --git a/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs b/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs index cfe9323c43f66..0fb29fcc041aa 100644 --- a/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs +++ b/crates/ruff/src/rules/pyflakes/rules/break_outside_loop.rs @@ -36,14 +36,12 @@ pub(crate) fn break_outside_loop<'a>( let mut child = stmt; for parent in parents { match parent { - Stmt::For(ast::StmtFor { orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | Stmt::While(ast::StmtWhile { orelse, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) | Stmt::While(ast::StmtWhile { orelse, .. }) => { if !orelse.contains(child) { return None; } } - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { break; } _ => {} diff --git a/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs b/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs index 5e773e4095224..15a0accc9cb9d 100644 --- a/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs +++ b/crates/ruff/src/rules/pyflakes/rules/continue_outside_loop.rs @@ -36,14 +36,12 @@ pub(crate) fn continue_outside_loop<'a>( let mut child = stmt; for parent in parents { match parent { - Stmt::For(ast::StmtFor { orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | Stmt::While(ast::StmtWhile { orelse, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) | Stmt::While(ast::StmtWhile { orelse, .. }) => { if !orelse.contains(child) { return None; } } - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { break; } _ => {} diff --git a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs index 86cd9e6ec75cd..5606cb74c32e5 100644 --- a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs +++ b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs @@ -1,5 +1,5 @@ -use ruff_python_ast::{Expr, Ranged}; -use ruff_python_parser::{lexer, Mode, StringKind, Tok}; +use ruff_python_ast::{Expr, PySourceType, Ranged}; +use ruff_python_parser::{lexer, AsMode, StringKind, Tok}; use ruff_text_size::{TextRange, TextSize}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -48,21 +48,21 @@ impl AlwaysAutofixableViolation for FStringMissingPlaceholders { } } -/// Find f-strings that don't contain any formatted values in a `JoinedStr`. +/// Find f-strings that don't contain any formatted values in an [`FString`]. fn find_useless_f_strings<'a>( expr: &'a Expr, locator: &'a Locator, + source_type: PySourceType, ) -> impl Iterator + 'a { let contents = locator.slice(expr.range()); - lexer::lex_starts_at(contents, Mode::Module, expr.start()) + lexer::lex_starts_at(contents, source_type.as_mode(), expr.start()) .flatten() .filter_map(|(tok, range)| match tok { Tok::String { kind: StringKind::FString | StringKind::RawFString, .. } => { - let first_char = - &locator.contents()[TextRange::at(range.start(), TextSize::from(1))]; + let first_char = locator.slice(TextRange::at(range.start(), TextSize::from(1))); // f"..." => f_position = 0 // fr"..." => f_position = 0 // rf"..." => f_position = 1 @@ -85,7 +85,9 @@ pub(crate) fn f_string_missing_placeholders(expr: &Expr, values: &[Expr], checke .iter() .any(|value| matches!(value, Expr::FormattedValue(_))) { - for (prefix_range, tok_range) in find_useless_f_strings(expr, checker.locator()) { + for (prefix_range, tok_range) in + find_useless_f_strings(expr, checker.locator(), checker.source_type) + { let mut diagnostic = Diagnostic::new(FStringMissingPlaceholders, tok_range); if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(convert_f_string_to_regular_string( @@ -125,7 +127,7 @@ fn convert_f_string_to_regular_string( .slice(TextRange::up_to(prefix_range.start())) .chars() .last() - .map_or(false, |char| content.starts_with(char)) + .is_some_and(|char| content.starts_with(char)) { content.insert(0, ' '); } diff --git a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs index 1876b65c05374..7fe38263ef348 100644 --- a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs +++ b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs @@ -130,7 +130,7 @@ pub(crate) fn repeated_keys(checker: &mut Checker, keys: &[Option], values }; match key { - Expr::Constant(_) | Expr::Tuple(_) | Expr::JoinedStr(_) => { + Expr::Constant(_) | Expr::Tuple(_) | Expr::FString(_) => { if checker.enabled(Rule::MultiValueRepeatedKeyLiteral) { let mut diagnostic = Diagnostic::new( MultiValueRepeatedKeyLiteral { diff --git a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs index 6028e5749197f..c6416d5e3d543 100644 --- a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs @@ -33,7 +33,7 @@ impl Violation for ReturnOutsideFunction { pub(crate) fn return_outside_function(checker: &mut Checker, stmt: &Stmt) { if matches!( - checker.semantic().scope().kind, + checker.semantic().current_scope().kind, ScopeKind::Class(_) | ScopeKind::Module ) { checker diff --git a/crates/ruff/src/rules/pyflakes/rules/strings.rs b/crates/ruff/src/rules/pyflakes/rules/strings.rs index a57ceead4d063..1fdfb10e47a3c 100644 --- a/crates/ruff/src/rules/pyflakes/rules/strings.rs +++ b/crates/ruff/src/rules/pyflakes/rules/strings.rs @@ -1,6 +1,6 @@ use std::string::ToString; -use ruff_python_ast::{self as ast, Constant, Expr, Identifier, Keyword}; +use ruff_python_ast::{self as ast, Constant, Expr, Identifier, Keyword, Ranged}; use ruff_text_size::TextRange; use rustc_hash::FxHashSet; @@ -570,23 +570,24 @@ pub(crate) fn percent_format_extra_named_arguments( if summary.num_positional > 0 { return; } - let Expr::Dict(ast::ExprDict { keys, .. }) = &right else { + let Expr::Dict(dict) = &right else { return; }; // If any of the keys are spread, abort. - if keys.iter().any(Option::is_none) { + if dict.keys.iter().any(Option::is_none) { return; } - let missing: Vec<(usize, &str)> = keys + let missing: Vec<(usize, &str)> = dict + .keys .iter() .enumerate() .filter_map(|(index, key)| match key { Some(Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. })) => { - if summary.keywords.contains(value) { + if summary.keywords.contains(value.as_str()) { None } else { Some((index, value.as_str())) @@ -613,7 +614,7 @@ pub(crate) fn percent_format_extra_named_arguments( diagnostic.try_set_fix(|| { let edit = remove_unused_format_arguments_from_dict( &indexes, - right, + dict, checker.locator(), checker.stylist(), )?; @@ -646,7 +647,7 @@ pub(crate) fn percent_format_missing_arguments( for key in keys.iter().flatten() { match key { Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) => { keywords.insert(value); @@ -739,9 +740,9 @@ pub(crate) fn percent_format_star_requires_sequence( /// F522 pub(crate) fn string_dot_format_extra_named_arguments( checker: &mut Checker, + call: &ast::ExprCall, summary: &FormatSummary, keywords: &[Keyword], - location: TextRange, ) { // If there are any **kwargs, abort. if has_star_star_kwargs(keywords) { @@ -773,14 +774,14 @@ pub(crate) fn string_dot_format_extra_named_arguments( .collect(); let mut diagnostic = Diagnostic::new( StringDotFormatExtraNamedArguments { missing: names }, - location, + call.range(), ); if checker.patch(diagnostic.kind.rule()) { let indexes: Vec = missing.iter().map(|(index, _)| *index).collect(); diagnostic.try_set_fix(|| { let edit = remove_unused_keyword_arguments_from_format_call( &indexes, - location, + call, checker.locator(), checker.stylist(), )?; @@ -793,9 +794,9 @@ pub(crate) fn string_dot_format_extra_named_arguments( /// F523 pub(crate) fn string_dot_format_extra_positional_arguments( checker: &mut Checker, + call: &ast::ExprCall, summary: &FormatSummary, args: &[Expr], - location: TextRange, ) { let missing: Vec = args .iter() @@ -817,7 +818,7 @@ pub(crate) fn string_dot_format_extra_positional_arguments( .map(ToString::to_string) .collect::>(), }, - location, + call.range(), ); if checker.patch(diagnostic.kind.rule()) { // We can only fix if the positional arguments we're removing don't require re-indexing @@ -849,7 +850,7 @@ pub(crate) fn string_dot_format_extra_positional_arguments( diagnostic.try_set_fix(|| { let edit = remove_unused_positional_arguments_from_format_call( &missing, - location, + call, checker.locator(), checker.stylist(), )?; @@ -863,10 +864,10 @@ pub(crate) fn string_dot_format_extra_positional_arguments( /// F524 pub(crate) fn string_dot_format_missing_argument( checker: &mut Checker, + call: &ast::ExprCall, summary: &FormatSummary, args: &[Expr], keywords: &[Keyword], - location: TextRange, ) { if has_star_args(args) || has_star_star_kwargs(keywords) { return; @@ -898,7 +899,7 @@ pub(crate) fn string_dot_format_missing_argument( if !missing.is_empty() { checker.diagnostics.push(Diagnostic::new( StringDotFormatMissingArguments { missing }, - location, + call.range(), )); } } @@ -906,12 +907,13 @@ pub(crate) fn string_dot_format_missing_argument( /// F525 pub(crate) fn string_dot_format_mixing_automatic( checker: &mut Checker, + call: &ast::ExprCall, summary: &FormatSummary, - location: TextRange, ) { if !(summary.autos.is_empty() || summary.indices.is_empty()) { - checker - .diagnostics - .push(Diagnostic::new(StringDotFormatMixingAutomatic, location)); + checker.diagnostics.push(Diagnostic::new( + StringDotFormatMixingAutomatic, + call.range(), + )); } } diff --git a/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs b/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs index 43c4eda5950ba..7e2d9fb8827e0 100644 --- a/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs +++ b/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs @@ -2,6 +2,7 @@ use std::string::ToString; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_semantic::{Scope, ScopeId}; use crate::checkers::ast::Checker; @@ -51,7 +52,7 @@ pub(crate) fn undefined_local( scope: &Scope, diagnostics: &mut Vec, ) { - if scope.kind.is_any_function() { + if scope.kind.is_function() { for (name, binding_id) in scope.bindings() { // If the variable shadows a binding in a parent scope... if let Some(shadowed_id) = checker.semantic().shadowed_binding(binding_id) { diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs b/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs index b71d048d20d3e..4b7e56c1bf3a4 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_semantic::Scope; use crate::checkers::ast::Checker; @@ -44,7 +45,7 @@ pub(crate) fn unused_annotation( && !binding.is_used() && !checker.settings.dummy_variable_rgx.is_match(name) { - Some((name.to_string(), binding.range)) + Some((name.to_string(), binding.range())) } else { None } diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_import.rs b/crates/ruff/src/rules/pyflakes/rules/unused_import.rs index 5ad4f41655d41..3c6c184289666 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_import.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_import.rs @@ -1,10 +1,13 @@ +use std::borrow::Cow; + use anyhow::Result; -use ruff_text_size::TextRange; use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::{Exceptions, NodeId, Scope}; +use ruff_python_ast::Ranged; +use ruff_python_semantic::{AnyImport, Exceptions, Imported, NodeId, Scope}; +use ruff_text_size::TextRange; use crate::autofix; use crate::checkers::ast::Checker; @@ -97,8 +100,8 @@ impl Violation for UnusedImport { pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut Vec) { // Collect all unused imports by statement. - let mut unused: FxHashMap<(NodeId, Exceptions), Vec> = FxHashMap::default(); - let mut ignored: FxHashMap<(NodeId, Exceptions), Vec> = FxHashMap::default(); + let mut unused: FxHashMap<(NodeId, Exceptions), Vec> = FxHashMap::default(); + let mut ignored: FxHashMap<(NodeId, Exceptions), Vec> = FxHashMap::default(); for binding_id in scope.binding_ids() { let binding = checker.semantic().binding(binding_id); @@ -111,32 +114,32 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut continue; } - let Some(qualified_name) = binding.qualified_name() else { + let Some(import) = binding.as_any_import() else { continue; }; - let Some(stmt_id) = binding.source else { + let Some(node_id) = binding.source else { continue; }; - let import = Import { - qualified_name, - range: binding.range, + let import = ImportBinding { + import, + range: binding.range(), parent_range: binding.parent_range(checker.semantic()), }; - if checker.rule_is_ignored(Rule::UnusedImport, import.range.start()) - || import.parent_range.map_or(false, |parent_range| { + if checker.rule_is_ignored(Rule::UnusedImport, import.start()) + || import.parent_range.is_some_and(|parent_range| { checker.rule_is_ignored(Rule::UnusedImport, parent_range.start()) }) { ignored - .entry((stmt_id, binding.exceptions)) + .entry((node_id, binding.exceptions)) .or_default() .push(import); } else { unused - .entry((stmt_id, binding.exceptions)) + .entry((node_id, binding.exceptions)) .or_default() .push(import); } @@ -147,26 +150,26 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut // Generate a diagnostic for every import, but share a fix across all imports within the same // statement (excluding those that are ignored). - for ((stmt_id, exceptions), imports) in unused { + for ((node_id, exceptions), imports) in unused { let in_except_handler = exceptions.intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); let multiple = imports.len() > 1; let fix = if !in_init && !in_except_handler && checker.patch(Rule::UnusedImport) { - fix_imports(checker, stmt_id, &imports).ok() + fix_imports(checker, node_id, &imports).ok() } else { None }; - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, } in imports { let mut diagnostic = Diagnostic::new( UnusedImport { - name: qualified_name.to_string(), + name: import.qualified_name(), context: if in_except_handler { Some(UnusedImportContext::ExceptHandler) } else if in_init { @@ -192,15 +195,15 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut // Separately, generate a diagnostic for every _ignored_ import, to ensure that the // suppression comments aren't marked as unused. - for Import { - qualified_name, + for ImportBinding { + import, range, parent_range, } in ignored.into_values().flatten() { let mut diagnostic = Diagnostic::new( UnusedImport { - name: qualified_name.to_string(), + name: import.qualified_name(), context: None, multiple: false, }, @@ -214,28 +217,42 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut } /// An unused import with its surrounding context. -struct Import<'a> { +#[derive(Debug)] +struct ImportBinding<'a> { /// The qualified name of the import (e.g., `typing.List` for `from typing import List`). - qualified_name: &'a str, + import: AnyImport<'a>, /// The trimmed range of the import (e.g., `List` in `from typing import List`). range: TextRange, /// The range of the import's parent statement. parent_range: Option, } +impl Ranged for ImportBinding<'_> { + fn range(&self) -> TextRange { + self.range + } +} + /// Generate a [`Fix`] to remove unused imports from a statement. -fn fix_imports(checker: &Checker, stmt_id: NodeId, imports: &[Import]) -> Result { - let stmt = checker.semantic().stmts[stmt_id]; - let parent = checker.semantic().stmts.parent(stmt); +fn fix_imports(checker: &Checker, node_id: NodeId, imports: &[ImportBinding]) -> Result { + let statement = checker.semantic().statement(node_id); + let parent = checker.semantic().parent_statement(node_id); + + let member_names: Vec> = imports + .iter() + .map(|ImportBinding { import, .. }| import) + .map(Imported::member_name) + .collect(); + let edit = autofix::edits::remove_unused_imports( - imports - .iter() - .map(|Import { qualified_name, .. }| *qualified_name), - stmt, + member_names.iter().map(AsRef::as_ref), + statement, parent, checker.locator(), checker.stylist(), checker.indexer(), )?; - Ok(Fix::automatic(edit).isolate(checker.isolation(parent))) + Ok(Fix::automatic(edit).isolate(Checker::isolation( + checker.semantic().parent_statement_id(node_id), + ))) } diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs index 50c17d1085af9..a748f2c433e2d 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs @@ -1,13 +1,13 @@ use itertools::Itertools; -use ruff_python_ast::{self as ast, Ranged, Stmt}; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::{TextRange, TextSize}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::contains_effect; -use ruff_python_semantic::Scope; +use ruff_python_ast::{self as ast, PySourceType, Ranged, Stmt}; +use ruff_python_parser::{lexer, AsMode, Tok}; +use ruff_python_semantic::{Binding, Scope}; use ruff_source_file::Locator; +use ruff_text_size::{TextRange, TextSize}; use crate::autofix::edits::delete_stmt; use crate::checkers::ast::Checker; @@ -62,12 +62,17 @@ impl Violation for UnusedVariable { } /// Return the [`TextRange`] of the token before the next match of the predicate -fn match_token_before(location: TextSize, locator: &Locator, f: F) -> Option +fn match_token_before( + location: TextSize, + locator: &Locator, + source_type: PySourceType, + f: F, +) -> Option where F: Fn(Tok) -> bool, { let contents = locator.after(location); - for ((_, range), (tok, _)) in lexer::lex_starts_at(contents, Mode::Module, location) + for ((_, range), (tok, _)) in lexer::lex_starts_at(contents, source_type.as_mode(), location) .flatten() .tuple_windows() { @@ -80,7 +85,12 @@ where /// Return the [`TextRange`] of the token after the next match of the predicate, skipping over /// any bracketed expressions. -fn match_token_after(location: TextSize, locator: &Locator, f: F) -> Option +fn match_token_after( + location: TextSize, + locator: &Locator, + source_type: PySourceType, + f: F, +) -> Option where F: Fn(Tok) -> bool, { @@ -91,7 +101,7 @@ where let mut sqb_count = 0u32; let mut brace_count = 0u32; - for ((tok, _), (_, range)) in lexer::lex_starts_at(contents, Mode::Module, location) + for ((tok, _), (_, range)) in lexer::lex_starts_at(contents, source_type.as_mode(), location) .flatten() .tuple_windows() { @@ -131,7 +141,12 @@ where /// Return the [`TextRange`] of the token matching the predicate or the first mismatched /// bracket, skipping over any bracketed expressions. -fn match_token_or_closing_brace(location: TextSize, locator: &Locator, f: F) -> Option +fn match_token_or_closing_brace( + location: TextSize, + locator: &Locator, + source_type: PySourceType, + f: F, +) -> Option where F: Fn(Tok) -> bool, { @@ -142,7 +157,7 @@ where let mut sqb_count = 0u32; let mut brace_count = 0u32; - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, location).flatten() { + for (tok, range) in lexer::lex_starts_at(contents, source_type.as_mode(), location).flatten() { match tok { Tok::Lpar => { par_count = par_count.saturating_add(1); @@ -186,17 +201,19 @@ where None } -/// Generate a [`Edit`] to remove an unused variable assignment, given the -/// enclosing [`Stmt`] and the [`TextRange`] of the variable binding. -fn remove_unused_variable( - stmt: &Stmt, - parent: Option<&Stmt>, - range: TextRange, - checker: &Checker, -) -> Option { +/// Generate a [`Edit`] to remove an unused variable assignment to a [`Binding`]. +fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option { + let node_id = binding.source?; + let statement = checker.semantic().statement(node_id); + let parent = checker.semantic().parent_statement(node_id); + let isolation = Checker::isolation(checker.semantic().parent_statement_id(node_id)); + // First case: simple assignment (`x = 1`) - if let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = stmt { - if let Some(target) = targets.iter().find(|target| range == target.range()) { + if let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = statement { + if let Some(target) = targets + .iter() + .find(|target| binding.range() == target.range()) + { if target.is_name_expr() { return if targets.len() > 1 || contains_effect(value, |id| checker.semantic().is_builtin(id)) @@ -204,14 +221,17 @@ fn remove_unused_variable( // If the expression is complex (`x = foo()`), remove the assignment, // but preserve the right-hand side. let start = target.start(); - let end = match_token_after(start, checker.locator(), |tok| tok == Tok::Equal)? + let end = + match_token_after(start, checker.locator(), checker.source_type, |tok| { + tok == Tok::Equal + })? .start(); let edit = Edit::deletion(start, end); Some(Fix::suggested(edit)) } else { // If (e.g.) assigning to a constant (`x = 1`), delete the entire statement. - let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - Some(Fix::suggested(edit).isolate(checker.isolation(parent))) + let edit = delete_stmt(statement, parent, checker.locator(), checker.indexer()); + Some(Fix::suggested(edit).isolate(isolation)) }; } } @@ -222,43 +242,51 @@ fn remove_unused_variable( target, value: Some(value), .. - }) = stmt + }) = statement { if target.is_name_expr() { return if contains_effect(value, |id| checker.semantic().is_builtin(id)) { // If the expression is complex (`x = foo()`), remove the assignment, // but preserve the right-hand side. - let start = stmt.start(); + let start = statement.start(); let end = - match_token_after(start, checker.locator(), |tok| tok == Tok::Equal)?.start(); + match_token_after(start, checker.locator(), checker.source_type, |tok| { + tok == Tok::Equal + })? + .start(); let edit = Edit::deletion(start, end); Some(Fix::suggested(edit)) } else { // If (e.g.) assigning to a constant (`x = 1`), delete the entire statement. - let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - Some(Fix::suggested(edit).isolate(checker.isolation(parent))) + let edit = delete_stmt(statement, parent, checker.locator(), checker.indexer()); + Some(Fix::suggested(edit).isolate(isolation)) }; } } // Third case: with_item (`with foo() as x:`) - if let Stmt::With(ast::StmtWith { items, .. }) = stmt { + if let Stmt::With(ast::StmtWith { items, .. }) = statement { // Find the binding that matches the given `Range`. // TODO(charlie): Store the `WithItem` in the `Binding`. for item in items { if let Some(optional_vars) = &item.optional_vars { - if optional_vars.range() == range { + if optional_vars.range() == binding.range() { // Find the first token before the `as` keyword. - let start = - match_token_before(item.context_expr.start(), checker.locator(), |tok| { - tok == Tok::As - })? - .end(); + let start = match_token_before( + item.context_expr.start(), + checker.locator(), + checker.source_type, + |tok| tok == Tok::As, + )? + .end(); // Find the first colon, comma, or closing bracket after the `as` keyword. - let end = match_token_or_closing_brace(start, checker.locator(), |tok| { - tok == Tok::Colon || tok == Tok::Comma - })? + let end = match_token_or_closing_brace( + start, + checker.locator(), + checker.source_type, + |tok| tok == Tok::Colon || tok == Tok::Comma, + )? .start(); let edit = Edit::deletion(start, end); @@ -273,11 +301,11 @@ fn remove_unused_variable( /// F841 pub(crate) fn unused_variable(checker: &Checker, scope: &Scope, diagnostics: &mut Vec) { - if scope.uses_locals() && scope.kind.is_any_function() { + if scope.uses_locals() && scope.kind.is_function() { return; } - for (name, range, source) in scope + for (name, binding) in scope .bindings() .map(|(name, binding_id)| (name, checker.semantic().binding(binding_id))) .filter_map(|(name, binding)| { @@ -286,25 +314,29 @@ pub(crate) fn unused_variable(checker: &Checker, scope: &Scope, diagnostics: &mu && !binding.is_global() && !binding.is_used() && !checker.settings.dummy_variable_rgx.is_match(name) - && name != "__tracebackhide__" - && name != "__traceback_info__" - && name != "__traceback_supplement__" - && name != "__debuggerskip__" + && !matches!( + name, + "__tracebackhide__" + | "__traceback_info__" + | "__traceback_supplement__" + | "__debuggerskip__" + ) { - return Some((name.to_string(), binding.range, binding.source)); + return Some((name, binding)); } None }) { - let mut diagnostic = Diagnostic::new(UnusedVariable { name }, range); + let mut diagnostic = Diagnostic::new( + UnusedVariable { + name: name.to_string(), + }, + binding.range(), + ); if checker.patch(diagnostic.kind.rule()) { - if let Some(source) = source { - let stmt = checker.semantic().stmts[source]; - let parent = checker.semantic().stmts.parent(stmt); - if let Some(fix) = remove_unused_variable(stmt, parent, range, checker) { - diagnostic.set_fix(fix); - } + if let Some(fix) = remove_unused_variable(binding, checker) { + diagnostic.set_fix(fix); } } diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs index 57c6b4b687e93..c58400e5819ee 100644 --- a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs @@ -1,10 +1,8 @@ use std::fmt; -use ruff_python_ast::{Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_semantic::ScopeKind; +use ruff_python_ast::{Expr, Ranged}; use crate::checkers::ast::Checker; @@ -26,12 +24,15 @@ impl fmt::Display for DeferralKeyword { } /// ## What it does -/// Checks for `yield` and `yield from` statements outside of functions. +/// Checks for `yield`, `yield from`, and `await` usages outside of functions. /// /// ## Why is this bad? -/// The use of a `yield` or `yield from` statement outside of a function will +/// The use of `yield`, `yield from`, or `await` outside of a function will /// raise a `SyntaxError`. /// +/// As an exception, `await` is allowed at the top level of a Jupyter notebook +/// (see: [autoawait]). +/// /// ## Example /// ```python /// class Foo: @@ -40,6 +41,8 @@ impl fmt::Display for DeferralKeyword { /// /// ## References /// - [Python documentation: `yield`](https://docs.python.org/3/reference/simple_stmts.html#the-yield-statement) +/// +/// [autoawait]: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html #[violation] pub struct YieldOutsideFunction { keyword: DeferralKeyword, @@ -53,17 +56,26 @@ impl Violation for YieldOutsideFunction { } } +/// F704 pub(crate) fn yield_outside_function(checker: &mut Checker, expr: &Expr) { - if matches!( - checker.semantic().scope().kind, - ScopeKind::Class(_) | ScopeKind::Module - ) { + let scope = checker.semantic().current_scope(); + if scope.kind.is_module() || scope.kind.is_class() { let keyword = match expr { Expr::Yield(_) => DeferralKeyword::Yield, Expr::YieldFrom(_) => DeferralKeyword::YieldFrom, Expr::Await(_) => DeferralKeyword::Await, - _ => panic!("Expected Expr::Yield | Expr::YieldFrom | Expr::Await"), + _ => return, }; + + // `await` is allowed at the top level of a Jupyter notebook. + // See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html. + if scope.kind.is_module() + && checker.source_type.is_ipynb() + && keyword == DeferralKeyword::Await + { + return; + } + checker.diagnostics.push(Diagnostic::new( YieldOutsideFunction { keyword }, expr.range(), diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_0.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_0.py.snap index 67c97bb6ba81c..3ae9fc730853f 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_0.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_0.py.snap @@ -151,6 +151,8 @@ F401_0.py:93:16: F401 [*] `x` imported but unused 92 92 | case 0,: 93 |- import x 94 93 | import y +95 94 | +96 95 | F401_0.py:94:16: F401 [*] `y` imported but unused | @@ -166,5 +168,100 @@ F401_0.py:94:16: F401 [*] `y` imported but unused 92 92 | case 0,: 93 93 | import x 94 |- import y +95 94 | +96 95 | +97 96 | # Test: access a sub-importation via an alias. + +F401_0.py:99:8: F401 [*] `foo.bar.baz` imported but unused + | + 97 | # Test: access a sub-importation via an alias. + 98 | import foo.bar as bop + 99 | import foo.bar.baz + | ^^^^^^^^^^^ F401 +100 | +101 | print(bop.baz.read_csv("test.csv")) + | + = help: Remove unused import: `foo.bar.baz` + +ℹ Fix +96 96 | +97 97 | # Test: access a sub-importation via an alias. +98 98 | import foo.bar as bop +99 |-import foo.bar.baz +100 99 | +101 100 | print(bop.baz.read_csv("test.csv")) +102 101 | + +F401_0.py:105:12: F401 [*] `a1` imported but unused + | +103 | # Test: isolated deletions. +104 | if TYPE_CHECKING: +105 | import a1 + | ^^ F401 +106 | +107 | import a2 + | + = help: Remove unused import: `a1` + +ℹ Fix +102 102 | +103 103 | # Test: isolated deletions. +104 104 | if TYPE_CHECKING: +105 |- import a1 +106 105 | +107 106 | import a2 +108 107 | + +F401_0.py:107:12: F401 [*] `a2` imported but unused + | +105 | import a1 +106 | +107 | import a2 + | ^^ F401 + | + = help: Remove unused import: `a2` + +ℹ Fix +104 104 | if TYPE_CHECKING: +105 105 | import a1 +106 106 | +107 |- import a2 +108 107 | +109 108 | +110 109 | match *0, 1, *2: + +F401_0.py:112:16: F401 [*] `b1` imported but unused + | +110 | match *0, 1, *2: +111 | case 0,: +112 | import b1 + | ^^ F401 +113 | +114 | import b2 + | + = help: Remove unused import: `b1` + +ℹ Fix +109 109 | +110 110 | match *0, 1, *2: +111 111 | case 0,: +112 |- import b1 +113 112 | +114 113 | import b2 + +F401_0.py:114:16: F401 [*] `b2` imported but unused + | +112 | import b1 +113 | +114 | import b2 + | ^^ F401 + | + = help: Remove unused import: `b2` + +ℹ Fix +111 111 | case 0,: +112 112 | import b1 +113 113 | +114 |- import b2 diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F521_F521.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F521_F521.py.snap index 59ae5d10a61b7..7e5cb863c741c 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F521_F521.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F521_F521.py.snap @@ -28,7 +28,7 @@ F521.py:3:1: F521 `.format` call has invalid format string: Expected '}' before 5 | "{:{:{}}}".format(1, 2, 3) | -F521.py:5:1: F521 `.format` call has invalid format string: Max string recursion exceeded +F521.py:5:1: F521 `.format` call has invalid format string: Max format placeholder recursion exceeded | 3 | "{foo[}".format(foo=1) 4 | # too much string recursion (placeholder-in-placeholder) diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F522_F522.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F522_F522.py.snap index 9ba19aa183578..8581e62d0b01b 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F522_F522.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F522_F522.py.snap @@ -33,7 +33,7 @@ F522.py:2:1: F522 [*] `.format` call has unused named argument(s): spam 2 |+"{bar}{}".format(1, bar=2, ) # F522 3 3 | "{bar:{spam}}".format(bar=2, spam=3) # No issues 4 4 | "{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 -5 5 | # Not fixable +5 5 | ('' F522.py:4:1: F522 [*] `.format` call has unused named argument(s): eggs, ham | @@ -41,8 +41,8 @@ F522.py:4:1: F522 [*] `.format` call has unused named argument(s): eggs, ham 3 | "{bar:{spam}}".format(bar=2, spam=3) # No issues 4 | "{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ F522 -5 | # Not fixable -6 | ('' +5 | ('' +6 | .format(x=2)) # F522 | = help: Remove extra named arguments: eggs, ham @@ -52,19 +52,25 @@ F522.py:4:1: F522 [*] `.format` call has unused named argument(s): eggs, ham 3 3 | "{bar:{spam}}".format(bar=2, spam=3) # No issues 4 |-"{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 4 |+"{bar:{spam}}".format(bar=2, spam=3, ) # F522 -5 5 | # Not fixable -6 6 | ('' -7 7 | .format(x=2)) +5 5 | ('' +6 6 | .format(x=2)) # F522 -F522.py:6:2: F522 `.format` call has unused named argument(s): x +F522.py:5:2: F522 [*] `.format` call has unused named argument(s): x | +3 | "{bar:{spam}}".format(bar=2, spam=3) # No issues 4 | "{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 -5 | # Not fixable -6 | ('' +5 | ('' | __^ -7 | | .format(x=2)) +6 | | .format(x=2)) # F522 | |_____________^ F522 | = help: Remove extra named arguments: x +ℹ Fix +3 3 | "{bar:{spam}}".format(bar=2, spam=3) # No issues +4 4 | "{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522 +5 5 | ('' +6 |- .format(x=2)) # F522 + 6 |+ .format()) # F522 + diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F523_F523.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F523_F523.py.snap index c566b9c64e0fb..f84189c4be3e6 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F523_F523.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F523_F523.py.snap @@ -243,13 +243,13 @@ F523.py:29:1: F523 `.format` call has unused arguments at position(s): 0 29 | "{1} {8}".format(0, 1) # F523, # F524 | ^^^^^^^^^^^^^^^^^^^^^^ F523 30 | -31 | # Not fixable +31 | # Multiline | = help: Remove extra positional arguments at position(s): 0 -F523.py:32:2: F523 `.format` call has unused arguments at position(s): 0 +F523.py:32:2: F523 [*] `.format` call has unused arguments at position(s): 0 | -31 | # Not fixable +31 | # Multiline 32 | ('' | __^ 33 | | .format(2)) @@ -257,4 +257,11 @@ F523.py:32:2: F523 `.format` call has unused arguments at position(s): 0 | = help: Remove extra positional arguments at position(s): 0 +ℹ Fix +30 30 | +31 31 | # Multiline +32 32 | ('' +33 |-.format(2)) + 33 |+.format()) + diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F841_F841_3.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F841_F841_3.py.snap index 348405332467b..85c614015c948 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F841_F841_3.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F841_F841_3.py.snap @@ -601,5 +601,76 @@ F841_3.py:155:17: F841 [*] Local variable `e` is assigned to but never used 155 |- except A as e : 155 |+ except A: 156 156 | print("oh no!") +157 157 | +158 158 | + +F841_3.py:160:5: F841 [*] Local variable `x` is assigned to but never used + | +159 | def f(): +160 | x = 1 + | ^ F841 +161 | y = 2 + | + = help: Remove assignment to unused variable `x` + +ℹ Suggested fix +157 157 | +158 158 | +159 159 | def f(): +160 |- x = 1 +161 160 | y = 2 +162 161 | +163 162 | + +F841_3.py:161:5: F841 [*] Local variable `y` is assigned to but never used + | +159 | def f(): +160 | x = 1 +161 | y = 2 + | ^ F841 + | + = help: Remove assignment to unused variable `y` + +ℹ Suggested fix +158 158 | +159 159 | def f(): +160 160 | x = 1 +161 |- y = 2 +162 161 | +163 162 | +164 163 | def f(): + +F841_3.py:165:5: F841 [*] Local variable `x` is assigned to but never used + | +164 | def f(): +165 | x = 1 + | ^ F841 +166 | +167 | y = 2 + | + = help: Remove assignment to unused variable `x` + +ℹ Suggested fix +162 162 | +163 163 | +164 164 | def f(): +165 |- x = 1 +166 165 | +167 166 | y = 2 + +F841_3.py:167:5: F841 [*] Local variable `y` is assigned to but never used + | +165 | x = 1 +166 | +167 | y = 2 + | ^ F841 + | + = help: Remove assignment to unused variable `y` + +ℹ Suggested fix +164 164 | def f(): +165 165 | x = 1 +166 166 | +167 |- y = 2 diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__f841_dummy_variable_rgx.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__f841_dummy_variable_rgx.snap index ff53df87e19d1..5197e53959bcb 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__f841_dummy_variable_rgx.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__f841_dummy_variable_rgx.snap @@ -256,4 +256,22 @@ F841_0.py:127:21: F841 Local variable `value` is assigned to but never used | = help: Remove assignment to unused variable `value` +F841_0.py:152:25: F841 [*] Local variable `_` is assigned to but never used + | +150 | try: +151 | pass +152 | except Exception as _: + | ^ F841 +153 | pass + | + = help: Remove assignment to unused variable `_` + +ℹ Fix +149 149 | def f(): +150 150 | try: +151 151 | pass +152 |- except Exception as _: + 152 |+ except Exception: +153 153 | pass + diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs index 4c4fdb1943096..934acc590aebf 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs @@ -46,9 +46,7 @@ pub(crate) fn deprecated_log_warn(checker: &mut Checker, func: &Expr) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["logging", "warn"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["logging", "warn"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/pylint/helpers.rs b/crates/ruff/src/rules/pylint/helpers.rs index 139485c87236a..60bb0dd22329d 100644 --- a/crates/ruff/src/rules/pylint/helpers.rs +++ b/crates/ruff/src/rules/pylint/helpers.rs @@ -1,20 +1,16 @@ use std::fmt; use ruff_python_ast as ast; -use ruff_python_ast::helpers::find_keyword; -use ruff_python_ast::{CmpOp, Constant, Expr, Keyword}; - +use ruff_python_ast::{Arguments, CmpOp, Constant, Expr}; use ruff_python_semantic::analyze::function_type; use ruff_python_semantic::{ScopeKind, SemanticModel}; use crate::settings::Settings; /// Returns the value of the `name` parameter to, e.g., a `TypeVar` constructor. -pub(super) fn type_param_name<'a>(args: &'a [Expr], keywords: &'a [Keyword]) -> Option<&'a str> { +pub(super) fn type_param_name(arguments: &Arguments) -> Option<&str> { // Handle both `TypeVar("T")` and `TypeVar(name="T")`. - let name_param = find_keyword(keywords, "name") - .map(|keyword| &keyword.value) - .or_else(|| args.get(0))?; + let name_param = arguments.find_argument("name", 0)?; if let Expr::Constant(ast::ExprConstant { value: Constant::Str(name), .. @@ -27,17 +23,12 @@ pub(super) fn type_param_name<'a>(args: &'a [Expr], keywords: &'a [Keyword]) -> } pub(super) fn in_dunder_init(semantic: &SemanticModel, settings: &Settings) -> bool { - let scope = semantic.scope(); - let (ScopeKind::Function(ast::StmtFunctionDef { - name, - decorator_list, - .. - }) - | ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef { + let scope = semantic.current_scope(); + let ScopeKind::Function(ast::StmtFunctionDef { name, decorator_list, .. - })) = scope.kind + }) = scope.kind else { return false; }; diff --git a/crates/ruff/src/rules/pylint/mod.rs b/crates/ruff/src/rules/pylint/mod.rs index 4e0a8f7e1b462..5d18261946bcd 100644 --- a/crates/ruff/src/rules/pylint/mod.rs +++ b/crates/ruff/src/rules/pylint/mod.rs @@ -18,8 +18,12 @@ mod tests { use crate::settings::Settings; use crate::test::test_path; - #[test_case(Rule::AwaitOutsideAsync, Path::new("await_outside_async.py"))] #[test_case(Rule::AssertOnStringLiteral, Path::new("assert_on_string_literal.py"))] + #[test_case(Rule::AwaitOutsideAsync, Path::new("await_outside_async.py"))] + #[test_case( + Rule::BadStringFormatCharacter, + Path::new("bad_string_format_character.py") + )] #[test_case(Rule::BadStrStripCall, Path::new("bad_str_strip_call.py"))] #[test_case(Rule::BadStringFormatType, Path::new("bad_string_format_type.py"))] #[test_case(Rule::BidirectionalUnicode, Path::new("bidirectional_unicode.py"))] @@ -46,6 +50,7 @@ mod tests { #[test_case(Rule::SysExitAlias, Path::new("sys_exit_alias_8.py"))] #[test_case(Rule::SysExitAlias, Path::new("sys_exit_alias_9.py"))] #[test_case(Rule::SysExitAlias, Path::new("sys_exit_alias_10.py"))] + #[test_case(Rule::SysExitAlias, Path::new("sys_exit_alias_11.py"))] #[test_case(Rule::ContinueInFinally, Path::new("continue_in_finally.py"))] #[test_case(Rule::GlobalStatement, Path::new("global_statement.py"))] #[test_case( @@ -122,11 +127,17 @@ mod tests { Rule::SubprocessPopenPreexecFn, Path::new("subprocess_popen_preexec_fn.py") )] + #[test_case( + Rule::SubprocessRunWithoutCheck, + Path::new("subprocess_run_without_check.py") + )] + #[test_case(Rule::BadDunderMethodName, Path::new("bad_dunder_method_name.py"))] + #[test_case(Rule::NoSelfUse, Path::new("no_self_use.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( Path::new("pylint").join(path).as_path(), - &Settings::for_rules(vec![rule_code]), + &Settings::for_rule(rule_code), )?; assert_messages!(snapshot, diagnostics); Ok(()) @@ -136,10 +147,8 @@ mod tests { fn repeated_isinstance_calls() -> Result<()> { let diagnostics = test_path( Path::new("pylint/repeated_isinstance_calls.py"), - &Settings { - target_version: PythonVersion::Py39, - ..Settings::for_rules(vec![Rule::RepeatedIsinstanceCalls]) - }, + &Settings::for_rule(Rule::RepeatedIsinstanceCalls) + .with_target_version(PythonVersion::Py39), )?; assert_messages!(diagnostics); Ok(()) @@ -149,10 +158,7 @@ mod tests { fn continue_in_finally() -> Result<()> { let diagnostics = test_path( Path::new("pylint/continue_in_finally.py"), - &Settings { - target_version: PythonVersion::Py37, - ..Settings::for_rules(vec![Rule::ContinueInFinally]) - }, + &Settings::for_rule(Rule::ContinueInFinally).with_target_version(PythonVersion::Py37), )?; assert_messages!(diagnostics); Ok(()) @@ -167,7 +173,7 @@ mod tests { allow_magic_value_types: vec![pylint::settings::ConstantType::Int], ..pylint::settings::Settings::default() }, - ..Settings::for_rules(vec![Rule::MagicValueComparison]) + ..Settings::for_rule(Rule::MagicValueComparison) }, )?; assert_messages!(diagnostics); @@ -183,7 +189,7 @@ mod tests { max_args: 4, ..pylint::settings::Settings::default() }, - ..Settings::for_rules(vec![Rule::TooManyArguments]) + ..Settings::for_rule(Rule::TooManyArguments) }, )?; assert_messages!(diagnostics); @@ -196,7 +202,7 @@ mod tests { Path::new("pylint/too_many_arguments_params.py"), &Settings { dummy_variable_rgx: Regex::new(r"skip_.*").unwrap(), - ..Settings::for_rules(vec![Rule::TooManyArguments]) + ..Settings::for_rule(Rule::TooManyArguments) }, )?; assert_messages!(diagnostics); @@ -212,7 +218,7 @@ mod tests { max_branches: 1, ..pylint::settings::Settings::default() }, - ..Settings::for_rules(vec![Rule::TooManyBranches]) + ..Settings::for_rule(Rule::TooManyBranches) }, )?; assert_messages!(diagnostics); @@ -228,7 +234,7 @@ mod tests { max_statements: 1, ..pylint::settings::Settings::default() }, - ..Settings::for_rules(vec![Rule::TooManyStatements]) + ..Settings::for_rule(Rule::TooManyStatements) }, )?; assert_messages!(diagnostics); @@ -244,7 +250,7 @@ mod tests { max_returns: 1, ..pylint::settings::Settings::default() }, - ..Settings::for_rules(vec![Rule::TooManyReturnStatements]) + ..Settings::for_rule(Rule::TooManyReturnStatements) }, )?; assert_messages!(diagnostics); diff --git a/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs b/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs index 46bbf2e86afe9..b88987fbae885 100644 --- a/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs +++ b/crates/ruff/src/rules/pylint/rules/assert_on_string_literal.rs @@ -71,7 +71,7 @@ pub(crate) fn assert_on_string_literal(checker: &mut Checker, test: &Expr) { } _ => {} }, - Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + Expr::FString(ast::ExprFString { values, .. }) => { checker.diagnostics.push(Diagnostic::new( AssertOnStringLiteral { kind: if values.iter().all(|value| match value { diff --git a/crates/ruff/src/rules/pylint/rules/bad_dunder_method_name.rs b/crates/ruff/src/rules/pylint/rules/bad_dunder_method_name.rs new file mode 100644 index 0000000000000..e7a3149e4fcf3 --- /dev/null +++ b/crates/ruff/src/rules/pylint/rules/bad_dunder_method_name.rs @@ -0,0 +1,195 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::identifier::Identifier; +use ruff_python_ast::Stmt; + +use crate::checkers::ast::Checker; + +/// ## What it does +/// Checks for any misspelled dunder name method and for any method +/// defined with `_..._` that's not one of the pre-defined methods +/// +/// The pre-defined methods encompass all of Python's standard dunder +/// methods. +/// +/// Note this includes all methods starting and ending with at least +/// one underscore to detect mistakes. +/// +/// ## Why is this bad? +/// Misspelled dunder name methods may cause your code to not function +/// as expected. +/// +/// Since dunder methods are associated with customizing the behavior +/// of a class in Python, introducing a dunder method such as `__foo__` +/// that diverges from standard Python dunder methods could potentially +/// confuse someone reading the code. +/// +/// ## Example +/// ```python +/// class Foo: +/// def __init_(self): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// class Foo: +/// def __init__(self): +/// ... +/// ``` +#[violation] +pub struct BadDunderMethodName { + name: String, +} + +impl Violation for BadDunderMethodName { + #[derive_message_formats] + fn message(&self) -> String { + let BadDunderMethodName { name } = self; + format!("Bad or misspelled dunder method name `{name}`. (bad-dunder-name)") + } +} + +/// PLW3201 +pub(crate) fn bad_dunder_method_name(checker: &mut Checker, class_body: &[Stmt]) { + for method in class_body + .iter() + .filter_map(ruff_python_ast::Stmt::as_function_def_stmt) + .filter(|method| { + if is_known_dunder_method(&method.name) { + return false; + } + method.name.starts_with('_') && method.name.ends_with('_') + }) + { + checker.diagnostics.push(Diagnostic::new( + BadDunderMethodName { + name: method.name.to_string(), + }, + method.identifier(), + )); + } +} + +/// Returns `true` if a method is a known dunder method. +fn is_known_dunder_method(method: &str) -> bool { + matches!( + method, + "__abs__" + | "__add__" + | "__aenter__" + | "__aexit__" + | "__aiter__" + | "__and__" + | "__anext__" + | "__await__" + | "__bool__" + | "__bytes__" + | "__call__" + | "__ceil__" + | "__class__" + | "__class_getitem__" + | "__complex__" + | "__contains__" + | "__copy__" + | "__deepcopy__" + | "__del__" + | "__delattr__" + | "__delete__" + | "__delitem__" + | "__dict__" + | "__dir__" + | "__divmod__" + | "__doc__" + | "__enter__" + | "__eq__" + | "__exit__" + | "__float__" + | "__floor__" + | "__floordiv__" + | "__format__" + | "__fspath__" + | "__ge__" + | "__get__" + | "__getattr__" + | "__getattribute__" + | "__getitem__" + | "__getnewargs__" + | "__getnewargs_ex__" + | "__getstate__" + | "__gt__" + | "__hash__" + | "__iadd__" + | "__iand__" + | "__ifloordiv__" + | "__ilshift__" + | "__imatmul__" + | "__imod__" + | "__imul__" + | "__init__" + | "__init_subclass__" + | "__instancecheck__" + | "__int__" + | "__invert__" + | "__ior__" + | "__ipow__" + | "__irshift__" + | "__isub__" + | "__iter__" + | "__itruediv__" + | "__ixor__" + | "__le__" + | "__len__" + | "__length_hint__" + | "__lshift__" + | "__lt__" + | "__matmul__" + | "__missing__" + | "__mod__" + | "__module__" + | "__mul__" + | "__ne__" + | "__neg__" + | "__new__" + | "__next__" + | "__or__" + | "__pos__" + | "__post_init__" + | "__pow__" + | "__radd__" + | "__rand__" + | "__rdivmod__" + | "__reduce__" + | "__reduce_ex__" + | "__repr__" + | "__reversed__" + | "__rfloordiv__" + | "__rlshift__" + | "__rmatmul__" + | "__rmod__" + | "__rmul__" + | "__ror__" + | "__round__" + | "__rpow__" + | "__rrshift__" + | "__rshift__" + | "__rsub__" + | "__rtruediv__" + | "__rxor__" + | "__set__" + | "__set_name__" + | "__setattr__" + | "__setitem__" + | "__setstate__" + | "__sizeof__" + | "__str__" + | "__sub__" + | "__subclasscheck__" + | "__subclasses__" + | "__subclasshook__" + | "__truediv__" + | "__trunc__" + | "__weakref__" + | "__xor__" + ) +} diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs new file mode 100644 index 0000000000000..cd8002bca0b43 --- /dev/null +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs @@ -0,0 +1,134 @@ +use std::str::FromStr; + +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::str::{leading_quote, trailing_quote}; +use ruff_python_ast::{Expr, Ranged}; +use ruff_python_literal::{ + cformat::{CFormatErrorType, CFormatString}, + format::FormatPart, + format::FromTemplate, + format::{FormatSpec, FormatSpecError, FormatString}, +}; +use ruff_python_parser::{lexer, Mode}; +use ruff_text_size::TextRange; + +use crate::checkers::ast::Checker; + +/// ## What it does +/// Checks for unsupported format types in format strings. +/// +/// ## Why is this bad? +/// An invalid format string character will result in an error at runtime. +/// +/// ## Example +/// ```python +/// # `z` is not a valid format type. +/// print("%z" % "1") +/// +/// print("{:z}".format("1")) +/// ``` +#[violation] +pub struct BadStringFormatCharacter { + format_char: char, +} + +impl Violation for BadStringFormatCharacter { + #[derive_message_formats] + fn message(&self) -> String { + let BadStringFormatCharacter { format_char } = self; + format!("Unsupported format character '{format_char}'") + } +} + +/// PLE1300 +/// Ex) `"{:z}".format("1")` +pub(crate) fn call(checker: &mut Checker, string: &str, range: TextRange) { + if let Ok(format_string) = FormatString::from_str(string) { + for part in &format_string.format_parts { + let FormatPart::Field { format_spec, .. } = part else { + continue; + }; + + match FormatSpec::parse(format_spec) { + Err(FormatSpecError::InvalidFormatType) => { + checker.diagnostics.push(Diagnostic::new( + BadStringFormatCharacter { + // The format type character is always the last one. + // More info in the official spec: + // https://docs.python.org/3/library/string.html#format-specification-mini-language + format_char: format_spec.chars().last().unwrap(), + }, + range, + )); + } + Err(_) => {} + Ok(FormatSpec::Static(_)) => {} + Ok(FormatSpec::Dynamic(format_spec)) => { + for placeholder in format_spec.placeholders { + let FormatPart::Field { format_spec, .. } = placeholder else { + continue; + }; + if let Err(FormatSpecError::InvalidFormatType) = + FormatSpec::parse(&format_spec) + { + checker.diagnostics.push(Diagnostic::new( + BadStringFormatCharacter { + // The format type character is always the last one. + // More info in the official spec: + // https://docs.python.org/3/library/string.html#format-specification-mini-language + format_char: format_spec.chars().last().unwrap(), + }, + range, + )); + } + } + } + } + } + } +} + +/// PLE1300 +/// Ex) `"%z" % "1"` +pub(crate) fn percent(checker: &mut Checker, expr: &Expr) { + // Grab each string segment (in case there's an implicit concatenation). + let mut strings: Vec = vec![]; + for (tok, range) in lexer::lex_starts_at( + checker.locator().slice(expr.range()), + Mode::Module, + expr.start(), + ) + .flatten() + { + if tok.is_string() { + strings.push(range); + } else if tok.is_percent() { + // Break as soon as we find the modulo symbol. + break; + } + } + + // If there are no string segments, abort. + if strings.is_empty() { + return; + } + + for range in &strings { + let string = checker.locator().slice(*range); + let (Some(leader), Some(trailer)) = (leading_quote(string), trailing_quote(string)) else { + return; + }; + let string = &string[leader.len()..string.len() - trailer.len()]; + + // Parse the format string (e.g. `"%s"`) into a list of `PercentFormat`. + if let Err(format_error) = CFormatString::from_str(string) { + if let CFormatErrorType::UnsupportedFormatChar(format_char) = format_error.typ { + checker.diagnostics.push(Diagnostic::new( + BadStringFormatCharacter { format_char }, + expr.range(), + )); + } + }; + } +} diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs index 857fc4e5db2b6..7ae0e648fefa5 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs @@ -2,14 +2,14 @@ use std::str::FromStr; use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString}; -use ruff_python_parser::{lexer, Mode}; +use ruff_python_parser::{lexer, AsMode}; use ruff_text_size::TextRange; use rustc_hash::FxHashMap; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::str::{leading_quote, trailing_quote}; -use ruff_python_semantic::analyze::type_inference::PythonType; +use ruff_python_semantic::analyze::type_inference::{NumberLike, PythonType, ResolvedPythonType}; use crate::checkers::ast::Checker; @@ -59,14 +59,16 @@ impl FormatType { | PythonType::Set | PythonType::Tuple | PythonType::Generator - | PythonType::Complex - | PythonType::Bool | PythonType::Ellipsis | PythonType::None => matches!( self, FormatType::Unknown | FormatType::String | FormatType::Repr ), - PythonType::Integer => matches!( + PythonType::Number(NumberLike::Complex | NumberLike::Bool) => matches!( + self, + FormatType::Unknown | FormatType::String | FormatType::Repr + ), + PythonType::Number(NumberLike::Integer) => matches!( self, FormatType::Unknown | FormatType::String @@ -75,7 +77,7 @@ impl FormatType { | FormatType::Float | FormatType::Number ), - PythonType::Float => matches!( + PythonType::Number(NumberLike::Float) => matches!( self, FormatType::Unknown | FormatType::String @@ -83,7 +85,6 @@ impl FormatType { | FormatType::Float | FormatType::Number ), - PythonType::Unknown => true, } } } @@ -118,16 +119,22 @@ fn collect_specs(formats: &[CFormatStrOrBytes]) -> Vec<&CFormatSpec> { /// Return `true` if the format string is equivalent to the constant type fn equivalent(format: &CFormatSpec, value: &Expr) -> bool { - let format: FormatType = format.format_char.into(); - let constant: PythonType = value.into(); - format.is_compatible_with(constant) + let format = FormatType::from(format.format_char); + match ResolvedPythonType::from(value) { + ResolvedPythonType::Atom(atom) => format.is_compatible_with(atom), + ResolvedPythonType::Union(atoms) => { + atoms.iter().all(|atom| format.is_compatible_with(*atom)) + } + ResolvedPythonType::Unknown => true, + ResolvedPythonType::TypeError => true, + } } -/// Return `true` if the [`Constnat`] aligns with the format type. +/// Return `true` if the [`Constant`] aligns with the format type. fn is_valid_constant(formats: &[CFormatStrOrBytes], value: &Expr) -> bool { let formats = collect_specs(formats); - // If there is more than one format, this is not valid python and we should - // return true so that no error is reported + // If there is more than one format, this is not valid Python and we should + // return true so that no error is reported. let [format] = formats.as_slice() else { return true; }; @@ -180,7 +187,10 @@ fn is_valid_dict( return true; }; if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(mapping_key), + value: + Constant::Str(ast::StringConstant { + value: mapping_key, .. + }), .. }) = key { @@ -203,7 +213,9 @@ pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: // Grab each string segment (in case there's an implicit concatenation). let content = checker.locator().slice(expr.range()); let mut strings: Vec = vec![]; - for (tok, range) in lexer::lex_starts_at(content, Mode::Module, expr.start()).flatten() { + for (tok, range) in + lexer::lex_starts_at(content, checker.source_type.as_mode(), expr.start()).flatten() + { if tok.is_string() { strings.push(range); } else if tok.is_percent() { @@ -240,8 +252,7 @@ pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: values, range: _, }) => is_valid_dict(&format_strings, keys, values), - Expr::Constant(_) => is_valid_constant(&format_strings, right), - _ => true, + _ => is_valid_constant(&format_strings, right), }; if !is_valid { checker diff --git a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs index f784489f609db..a6d34938fd68c 100644 --- a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs +++ b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs @@ -67,8 +67,8 @@ pub(crate) fn compare_to_empty_string( // DataFrame and np.ndarray indexing. if checker .semantic() - .expr_ancestors() - .any(|parent| parent.is_subscript_expr()) + .current_expressions() + .any(Expr::is_subscript_expr) { return; } diff --git a/crates/ruff/src/rules/pylint/rules/comparison_with_itself.rs b/crates/ruff/src/rules/pylint/rules/comparison_with_itself.rs index 66bdad7880be3..f6d94f67fa9c0 100644 --- a/crates/ruff/src/rules/pylint/rules/comparison_with_itself.rs +++ b/crates/ruff/src/rules/pylint/rules/comparison_with_itself.rs @@ -1,8 +1,8 @@ use itertools::Itertools; -use ruff_python_ast::{CmpOp, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{CmpOp, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::rules::pylint::helpers::CmpOpExt; @@ -51,17 +51,64 @@ pub(crate) fn comparison_with_itself( .tuple_windows() .zip(ops) { - if let (Expr::Name(left), Expr::Name(right)) = (left, right) { - if left.id == right.id { + match (left, right) { + // Ex) `foo == foo` + (Expr::Name(left_name), Expr::Name(right_name)) if left_name.id == right_name.id => { checker.diagnostics.push(Diagnostic::new( ComparisonWithItself { - left: left.id.to_string(), + left: checker.generator().expr(left), op: *op, - right: right.id.to_string(), + right: checker.generator().expr(right), }, - left.range(), + left_name.range(), )); } + // Ex) `id(foo) == id(foo)` + (Expr::Call(left_call), Expr::Call(right_call)) => { + // Both calls must take a single argument, of the same name. + if !left_call.arguments.keywords.is_empty() + || !right_call.arguments.keywords.is_empty() + { + continue; + } + let [Expr::Name(left_arg)] = left_call.arguments.args.as_slice() else { + continue; + }; + let [Expr::Name(right_right)] = right_call.arguments.args.as_slice() else { + continue; + }; + if left_arg.id != right_right.id { + continue; + } + + // Both calls must be to the same function. + let Expr::Name(left_func) = left_call.func.as_ref() else { + continue; + }; + let Expr::Name(right_func) = right_call.func.as_ref() else { + continue; + }; + if left_func.id != right_func.id { + continue; + } + + // The call must be to pure function, like `id`. + if matches!( + left_func.id.as_str(), + "id" | "len" | "type" | "int" | "bool" | "str" | "repr" | "bytes" + ) && checker.semantic().is_builtin(&left_func.id) + { + checker.diagnostics.push(Diagnostic::new( + ComparisonWithItself { + left: checker.generator().expr(left), + op: *op, + right: checker.generator().expr(right), + }, + left_call.range(), + )); + } + } + _ => {} } } } diff --git a/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs b/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs index 90f75b83e49c6..78e4ae85aaf74 100644 --- a/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs +++ b/crates/ruff/src/rules/pylint/rules/continue_in_finally.rs @@ -64,16 +64,14 @@ fn traverse_body(checker: &mut Checker, body: &[Stmt]) { traverse_body(checker, &clause.body); } } - Stmt::Try(ast::StmtTry { body, orelse, .. }) - | Stmt::TryStar(ast::StmtTryStar { body, orelse, .. }) => { + Stmt::Try(ast::StmtTry { body, orelse, .. }) => { traverse_body(checker, body); traverse_body(checker, orelse); } - Stmt::For(ast::StmtFor { orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | Stmt::While(ast::StmtWhile { orelse, .. }) => traverse_body(checker, orelse), - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { + Stmt::For(ast::StmtFor { orelse, .. }) | Stmt::While(ast::StmtWhile { orelse, .. }) => { + traverse_body(checker, orelse); + } + Stmt::With(ast::StmtWith { body, .. }) => { traverse_body(checker, body); } Stmt::Match(ast::StmtMatch { cases, .. }) => { diff --git a/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs b/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs index 4fe7b001923e5..8793244068917 100644 --- a/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs +++ b/crates/ruff/src/rules/pylint/rules/duplicate_bases.rs @@ -1,6 +1,6 @@ use std::hash::BuildHasherDefault; -use ruff_python_ast::{self as ast, Expr, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged}; use rustc_hash::FxHashSet; use ruff_diagnostics::{Diagnostic, Violation}; @@ -51,7 +51,11 @@ impl Violation for DuplicateBases { } /// PLE0241 -pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, bases: &[Expr]) { +pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, arguments: Option<&Arguments>) { + let Some(Arguments { args: bases, .. }) = arguments else { + return; + }; + let mut seen: FxHashSet<&str> = FxHashSet::with_capacity_and_hasher(bases.len(), BuildHasherDefault::default()); for base in bases { diff --git a/crates/ruff/src/rules/pylint/rules/duplicate_value.rs b/crates/ruff/src/rules/pylint/rules/duplicate_value.rs deleted file mode 100644 index 194e0bc55dc04..0000000000000 --- a/crates/ruff/src/rules/pylint/rules/duplicate_value.rs +++ /dev/null @@ -1,57 +0,0 @@ -use ruff_python_ast::{self as ast, Expr, Ranged}; -use rustc_hash::FxHashSet; - -use ruff_diagnostics::{Diagnostic, Violation}; -use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::comparable::ComparableExpr; - -use crate::checkers::ast::Checker; - -/// ## What it does -/// Checks for set literals that contain duplicate values. -/// -/// ## Why is this bad? -/// In Python, sets are unordered collections of unique elements. Including a -/// duplicate value in a set literal is redundant, and may be indicative of a -/// mistake. -/// -/// ## Example -/// ```python -/// {1, 2, 3, 1} -/// ``` -/// -/// Use instead: -/// ```python -/// {1, 2, 3} -/// ``` -#[violation] -pub struct DuplicateValue { - value: String, -} - -impl Violation for DuplicateValue { - #[derive_message_formats] - fn message(&self) -> String { - let DuplicateValue { value } = self; - format!("Duplicate value `{value}` in set") - } -} - -/// PLW0130 -pub(crate) fn duplicate_value(checker: &mut Checker, elts: &Vec) { - let mut seen_values: FxHashSet = FxHashSet::default(); - for elt in elts { - if let Expr::Constant(ast::ExprConstant { value, .. }) = elt { - let comparable_value: ComparableExpr = elt.into(); - - if !seen_values.insert(comparable_value) { - checker.diagnostics.push(Diagnostic::new( - DuplicateValue { - value: checker.generator().constant(value), - }, - elt.range(), - )); - } - }; - } -} diff --git a/crates/ruff/src/rules/pylint/rules/eq_without_hash.rs b/crates/ruff/src/rules/pylint/rules/eq_without_hash.rs index 3cd0f5ce5e3e0..134538534e22c 100644 --- a/crates/ruff/src/rules/pylint/rules/eq_without_hash.rs +++ b/crates/ruff/src/rules/pylint/rules/eq_without_hash.rs @@ -1,7 +1,7 @@ -use ruff_python_ast::{self as ast, Ranged, Stmt}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use crate::checkers::ast::Checker; @@ -65,12 +65,29 @@ fn has_eq_without_hash(body: &[Stmt]) -> bool { let mut has_hash = false; let mut has_eq = false; for statement in body { - let Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) = statement else { - continue; - }; - match name.as_str() { - "__hash__" => has_hash = true, - "__eq__" => has_eq = true, + match statement { + Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { + let [Expr::Name(ast::ExprName { id, .. })] = targets.as_slice() else { + continue; + }; + + // Check if `__hash__` was explicitly set to `None`, as in: + // ```python + // class Class: + // def __eq__(self, other): + // return True + // + // __hash__ = None + // ``` + if id == "__hash__" && is_const_none(value) { + has_hash = true; + } + } + Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() { + "__hash__" => has_hash = true, + "__eq__" => has_eq = true, + _ => {} + }, _ => {} } } diff --git a/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs b/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs index dc0903428bd2f..8af36075dc4a6 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_all_format.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_semantic::Binding; /// ## What it does @@ -37,7 +38,7 @@ impl Violation for InvalidAllFormat { /// PLE0605 pub(crate) fn invalid_all_format(binding: &Binding) -> Option { if binding.is_invalid_all_format() { - Some(Diagnostic::new(InvalidAllFormat, binding.range)) + Some(Diagnostic::new(InvalidAllFormat, binding.range())) } else { None } diff --git a/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs b/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs index 378302c4e48dc..2a1fdffe434d2 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_all_object.rs @@ -1,5 +1,6 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::Ranged; use ruff_python_semantic::Binding; /// ## What it does @@ -37,7 +38,7 @@ impl Violation for InvalidAllObject { /// PLE0604 pub(crate) fn invalid_all_object(binding: &Binding) -> Option { if binding.is_invalid_all_object() { - Some(Diagnostic::new(InvalidAllObject, binding.range)) + Some(Diagnostic::new(InvalidAllObject, binding.range())) } else { None } diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs index 5c7011a009b69..a6972b1d26be1 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs @@ -1,31 +1,33 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Operator, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Constant, Expr, Operator, Ranged}; use crate::checkers::ast::Checker; /// ## What it does -/// Checks for `env.getenv` calls with invalid default values. +/// Checks for `os.getenv` calls with invalid default values. /// /// ## Why is this bad? -/// If an environment variable is set, `env.getenv` will return its value as -/// a string. If the environment variable is _not_ set, `env.getenv` will +/// If an environment variable is set, `os.getenv` will return its value as +/// a string. If the environment variable is _not_ set, `os.getenv` will /// return `None`, or the default value if one is provided. /// /// If the default value is not a string or `None`, then it will be -/// inconsistent with the return type of `env.getenv`, which can lead to +/// inconsistent with the return type of `os.getenv`, which can lead to /// confusing behavior. /// /// ## Example /// ```python -/// int(env.getenv("FOO", 1)) +/// import os +/// +/// int(os.getenv("FOO", 1)) /// ``` /// /// Use instead: /// ```python -/// int(env.getenv("FOO", "1")) +/// import os +/// +/// int(os.getenv("FOO", "1")) /// ``` #[violation] pub struct InvalidEnvvarDefault; @@ -73,29 +75,19 @@ fn is_valid_default(expr: &Expr) -> bool { Expr::Constant(ast::ExprConstant { value: Constant::Str { .. } | Constant::None { .. }, .. - }) | Expr::JoinedStr(_) + }) | Expr::FString(_) ) } /// PLW1508 -pub(crate) fn invalid_envvar_default( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn invalid_envvar_default(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["os", "getenv"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["os", "getenv"])) { // Find the `default` argument, if it exists. - let Some(expr) = args - .get(1) - .or_else(|| find_keyword(keywords, "default").map(|keyword| &keyword.value)) - else { + let Some(expr) = call.arguments.find_argument("default", 1) else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs index 2f0acee2dbb4a..174a6a1359743 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Operator, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Ranged}; +use ruff_python_semantic::analyze::type_inference::{PythonType, ResolvedPythonType}; use crate::checkers::ast::Checker; @@ -34,72 +33,27 @@ impl Violation for InvalidEnvvarValue { } } -fn is_valid_key(expr: &Expr) -> bool { - // We can't infer the types of these defaults, so assume they're valid. - if matches!( - expr, - Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) - ) { - return true; - } - - // Allow string concatenation. - if let Expr::BinOp(ast::ExprBinOp { - left, - right, - op: Operator::Add, - range: _, - }) = expr - { - return is_valid_key(left) && is_valid_key(right); - } - - // Allow string formatting. - if let Expr::BinOp(ast::ExprBinOp { - left, - op: Operator::Mod, - .. - }) = expr - { - return is_valid_key(left); - } - - // Otherwise, the default must be a string. - matches!( - expr, - Expr::Constant(ast::ExprConstant { - value: Constant::Str { .. }, - .. - }) | Expr::JoinedStr(_) - ) -} - /// PLE1507 -pub(crate) fn invalid_envvar_value( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn invalid_envvar_value(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["os", "getenv"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["os", "getenv"])) { // Find the `key` argument, if it exists. - let Some(expr) = args - .get(0) - .or_else(|| find_keyword(keywords, "key").map(|keyword| &keyword.value)) - else { + let Some(expr) = call.arguments.find_argument("key", 0) else { return; }; - if !is_valid_key(expr) { - checker - .diagnostics - .push(Diagnostic::new(InvalidEnvvarValue, expr.range())); + if matches!( + ResolvedPythonType::from(expr), + ResolvedPythonType::Unknown | ResolvedPythonType::Atom(PythonType::String) + ) { + return; } + + checker + .diagnostics + .push(Diagnostic::new(InvalidEnvvarValue, expr.range())); } } diff --git a/crates/ruff/src/rules/pylint/rules/invalid_str_return.rs b/crates/ruff/src/rules/pylint/rules/invalid_str_return.rs index 74eddd0f92ee4..3dd341a8f5f28 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_str_return.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_str_return.rs @@ -3,7 +3,7 @@ use ruff_python_ast::{Ranged, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::{helpers::ReturnStatementVisitor, statement_visitor::StatementVisitor}; -use ruff_python_semantic::analyze::type_inference::PythonType; +use ruff_python_semantic::analyze::type_inference::{PythonType, ResolvedPythonType}; use crate::checkers::ast::Checker; @@ -29,7 +29,7 @@ pub(crate) fn invalid_str_return(checker: &mut Checker, name: &str, body: &[Stmt return; } - if !checker.semantic().scope().kind.is_class() { + if !checker.semantic().current_scope().kind.is_class() { return; } @@ -41,10 +41,9 @@ pub(crate) fn invalid_str_return(checker: &mut Checker, name: &str, body: &[Stmt for stmt in returns { if let Some(value) = stmt.value.as_deref() { - // Disallow other, non- if !matches!( - PythonType::from(value), - PythonType::String | PythonType::Unknown + ResolvedPythonType::from(value), + ResolvedPythonType::Unknown | ResolvedPythonType::Atom(PythonType::String) ) { checker .diagnostics diff --git a/crates/ruff/src/rules/pylint/rules/logging.rs b/crates/ruff/src/rules/pylint/rules/logging.rs index 1c3bbdefd16cb..1c05df692f16f 100644 --- a/crates/ruff/src/rules/pylint/rules/logging.rs +++ b/crates/ruff/src/rules/pylint/rules/logging.rs @@ -1,8 +1,6 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::CallArguments; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use ruff_python_semantic::analyze::logging; use ruff_python_stdlib::logging::LoggingLevel; @@ -86,23 +84,23 @@ impl Violation for LoggingTooManyArgs { /// PLE1205 /// PLE1206 -pub(crate) fn logging_call( - checker: &mut Checker, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn logging_call(checker: &mut Checker, call: &ast::ExprCall) { // If there are any starred arguments, abort. - if args.iter().any(Expr::is_starred_expr) { + if call.arguments.args.iter().any(Expr::is_starred_expr) { return; } // If there are any starred keyword arguments, abort. - if keywords.iter().any(|keyword| keyword.arg.is_none()) { + if call + .arguments + .keywords + .iter() + .any(|keyword| keyword.arg.is_none()) + { return; } - let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func else { + let Expr::Attribute(ast::ExprAttribute { attr, .. }) = call.func.as_ref() else { return; }; @@ -110,16 +108,19 @@ pub(crate) fn logging_call( return; } - let call_args = CallArguments::new(args, keywords); let Some(Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. - })) = call_args.argument("msg", 0) + })) = call.arguments.find_positional(0) else { return; }; - if !logging::is_logger_candidate(func, checker.semantic(), &checker.settings.logger_objects) { + if !logging::is_logger_candidate( + &call.func, + checker.semantic(), + &checker.settings.logger_objects, + ) { return; } @@ -135,22 +136,22 @@ pub(crate) fn logging_call( return; } - let message_args = call_args.num_args() - 1; + let num_message_args = call.arguments.args.len() - 1; + let num_keywords = call.arguments.keywords.len(); if checker.enabled(Rule::LoggingTooManyArgs) { - if summary.num_positional < message_args { + if summary.num_positional < num_message_args { checker .diagnostics - .push(Diagnostic::new(LoggingTooManyArgs, func.range())); + .push(Diagnostic::new(LoggingTooManyArgs, call.func.range())); } } if checker.enabled(Rule::LoggingTooFewArgs) { - if message_args > 0 && call_args.num_kwargs() == 0 && summary.num_positional > message_args - { + if num_message_args > 0 && num_keywords == 0 && summary.num_positional > num_message_args { checker .diagnostics - .push(Diagnostic::new(LoggingTooFewArgs, func.range())); + .push(Diagnostic::new(LoggingTooFewArgs, call.func.range())); } } } diff --git a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs index 0c7385c41089d..3f96d789c2f11 100644 --- a/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs +++ b/crates/ruff/src/rules/pylint/rules/magic_value_comparison.rs @@ -79,7 +79,9 @@ fn is_magic_value(constant: &Constant, allowed_types: &[ConstantType]) -> bool { Constant::Bool(_) => false, Constant::Ellipsis => false, // Otherwise, special-case some common string and integer types. - Constant::Str(value) => !matches!(value.as_str(), "" | "__main__"), + Constant::Str(ast::StringConstant { value, .. }) => { + !matches!(value.as_str(), "" | "__main__") + } Constant::Int(value) => !matches!(value.try_into(), Ok(0 | 1)), Constant::Bytes(_) => true, Constant::Float(_) => true, diff --git a/crates/ruff/src/rules/pylint/rules/mod.rs b/crates/ruff/src/rules/pylint/rules/mod.rs index 1cc36b22937eb..532f267ce4ed6 100644 --- a/crates/ruff/src/rules/pylint/rules/mod.rs +++ b/crates/ruff/src/rules/pylint/rules/mod.rs @@ -1,6 +1,8 @@ pub(crate) use assert_on_string_literal::*; pub(crate) use await_outside_async::*; +pub(crate) use bad_dunder_method_name::*; pub(crate) use bad_str_strip_call::*; +pub(crate) use bad_string_format_character::BadStringFormatCharacter; pub(crate) use bad_string_format_type::*; pub(crate) use bidirectional_unicode::*; pub(crate) use binary_op_exception::*; @@ -27,6 +29,7 @@ pub(crate) use magic_value_comparison::*; pub(crate) use manual_import_from::*; pub(crate) use named_expr_without_context::*; pub(crate) use nested_min_max::*; +pub(crate) use no_self_use::*; pub(crate) use nonlocal_without_binding::*; pub(crate) use property_with_parameters::*; pub(crate) use redefined_loop_name::*; @@ -36,6 +39,7 @@ pub(crate) use return_in_init::*; pub(crate) use self_assigning_variable::*; pub(crate) use single_string_slots::*; pub(crate) use subprocess_popen_preexec_fn::*; +pub(crate) use subprocess_run_without_check::*; pub(crate) use sys_exit_alias::*; pub(crate) use too_many_arguments::*; pub(crate) use too_many_branches::*; @@ -54,7 +58,9 @@ pub(crate) use yield_in_init::*; mod assert_on_string_literal; mod await_outside_async; +mod bad_dunder_method_name; mod bad_str_strip_call; +pub(crate) mod bad_string_format_character; mod bad_string_format_type; mod bidirectional_unicode; mod binary_op_exception; @@ -81,6 +87,7 @@ mod magic_value_comparison; mod manual_import_from; mod named_expr_without_context; mod nested_min_max; +mod no_self_use; mod nonlocal_without_binding; mod property_with_parameters; mod redefined_loop_name; @@ -90,6 +97,7 @@ mod return_in_init; mod self_assigning_variable; mod single_string_slots; mod subprocess_popen_preexec_fn; +mod subprocess_run_without_check; mod sys_exit_alias; mod too_many_arguments; mod too_many_branches; diff --git a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs index f154bae763953..b342a4edc46af 100644 --- a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs +++ b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Expr, Keyword, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Ranged}; use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -95,8 +95,12 @@ fn collect_nested_args(min_max: MinMax, args: &[Expr], semantic: &SemanticModel) for arg in args { if let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) = arg { @@ -135,14 +139,18 @@ pub(crate) fn nested_min_max( return; }; - if args.len() == 1 - && matches!(&args[0], Expr::Call(ast::ExprCall { args, .. }) if args.len() == 1) + if matches!(&args, [Expr::Call(ast::ExprCall { arguments: Arguments {args, .. }, .. })] if args.len() == 1) { return; } if args.iter().any(|arg| { - let Expr::Call(ast::ExprCall { func, keywords, .. }) = arg else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { keywords, .. }, + .. + }) = arg + else { return false; }; MinMax::try_from_call(func.as_ref(), keywords.as_ref(), checker.semantic()) == Some(min_max) @@ -152,8 +160,11 @@ pub(crate) fn nested_min_max( if !checker.indexer().has_comments(expr, checker.locator()) { let flattened_expr = Expr::Call(ast::ExprCall { func: Box::new(func.clone()), - args: collect_nested_args(min_max, args, checker.semantic()), - keywords: keywords.to_owned(), + arguments: Arguments { + args: collect_nested_args(min_max, args, checker.semantic()), + keywords: keywords.to_owned(), + range: TextRange::default(), + }, range: TextRange::default(), }); diagnostic.set_fix(Fix::suggested(Edit::range_replacement( diff --git a/crates/ruff/src/rules/pylint/rules/no_self_use.rs b/crates/ruff/src/rules/pylint/rules/no_self_use.rs new file mode 100644 index 0000000000000..3aa6e8d9e0cfd --- /dev/null +++ b/crates/ruff/src/rules/pylint/rules/no_self_use.rs @@ -0,0 +1,120 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::call_path::{from_qualified_name, CallPath}; +use ruff_python_ast::{self as ast, ParameterWithDefault, Ranged}; +use ruff_python_semantic::{ + analyze::{function_type, visibility}, + Scope, ScopeKind, +}; + +use crate::{checkers::ast::Checker, rules::flake8_unused_arguments::helpers}; + +/// ## What it does +/// Checks for the presence of unused `self` parameter in methods definitions. +/// +/// ## Why is this bad? +/// Unused `self` parameters are usually a sign of a method that could be +/// replaced by a function or a static method. +/// +/// ## Example +/// ```python +/// class Person: +/// def greeting(self): +/// print("Greetings friend!") +/// ``` +/// +/// Use instead: +/// ```python +/// class Person: +/// @staticmethod +/// def greeting(): +/// print(f"Greetings friend!") +/// ``` +#[violation] +pub struct NoSelfUse { + method_name: String, +} + +impl Violation for NoSelfUse { + #[derive_message_formats] + fn message(&self) -> String { + let NoSelfUse { method_name } = self; + format!("Method `{method_name}` could be a function or static method") + } +} + +/// PLR6301 +pub(crate) fn no_self_use(checker: &Checker, scope: &Scope, diagnostics: &mut Vec) { + let Some(parent) = &checker.semantic().first_non_type_parent_scope(scope) else { + return; + }; + + let ScopeKind::Function(ast::StmtFunctionDef { + name, + parameters, + body, + decorator_list, + .. + }) = scope.kind + else { + return; + }; + + if !matches!( + function_type::classify( + name, + decorator_list, + parent, + checker.semantic(), + &checker.settings.pep8_naming.classmethod_decorators, + &checker.settings.pep8_naming.staticmethod_decorators, + ), + function_type::FunctionType::Method + ) { + return; + } + + let property_decorators = checker + .settings + .pydocstyle + .property_decorators + .iter() + .map(|decorator| from_qualified_name(decorator)) + .collect::>(); + + if helpers::is_empty(body) + || visibility::is_magic(name) + || visibility::is_abstract(decorator_list, checker.semantic()) + || visibility::is_override(decorator_list, checker.semantic()) + || visibility::is_overload(decorator_list, checker.semantic()) + || visibility::is_property(decorator_list, &property_decorators, checker.semantic()) + { + return; + } + + // Identify the `self` parameter. + let Some(parameter) = parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .next() + .map(ParameterWithDefault::as_parameter) + else { + return; + }; + + if parameter.name.as_str() == "self" + && scope + .get("self") + .map(|binding_id| checker.semantic().binding(binding_id)) + .is_some_and(|binding| binding.kind.is_argument() && !binding.is_used()) + { + diagnostics.push(Diagnostic::new( + NoSelfUse { + method_name: name.to_string(), + }, + parameter.range(), + )); + } +} diff --git a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs index f177480345f4d..42a7db35d28b9 100644 --- a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs +++ b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, Stmt}; +use ruff_python_ast::{self as ast, Decorator, Expr, Parameters, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -51,7 +51,7 @@ pub(crate) fn property_with_parameters( checker: &mut Checker, stmt: &Stmt, decorator_list: &[Decorator], - args: &Arguments, + parameters: &Parameters, ) { if !decorator_list .iter() @@ -59,11 +59,11 @@ pub(crate) fn property_with_parameters( { return; } - if args + if parameters .posonlyargs .iter() - .chain(&args.args) - .chain(&args.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) .count() > 1 && checker.semantic().is_builtin("property") diff --git a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs index 8ae53d47e4a68..23ec06ba31f28 100644 --- a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs +++ b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs @@ -1,7 +1,7 @@ use std::{fmt, iter}; use regex::Regex; -use ruff_python_ast::{self as ast, Expr, ExprContext, Ranged, Stmt, WithItem}; +use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Ranged, Stmt, WithItem}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -147,9 +147,7 @@ impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { fn visit_stmt(&mut self, stmt: &'b Stmt) { // Collect target expressions. match stmt { - // For and async for. - Stmt::For(ast::StmtFor { target, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { target, .. }) => { + Stmt::For(ast::StmtFor { target, .. }) => { self.assignment_targets.extend( assignment_targets_from_expr(target, self.dummy_variable_rgx).map(|expr| { ExprWithInnerBindingKind { @@ -159,7 +157,6 @@ impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { }), ); } - // With. Stmt::With(ast::StmtWith { items, .. }) => { self.assignment_targets.extend( assignment_targets_from_with_items(items, self.dummy_variable_rgx).map( @@ -170,13 +167,13 @@ impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { ), ); } - // Assignment, augmented assignment, and annotated assignment. Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { // Check for single-target assignments which are of the // form `x = cast(..., x)`. - if targets.first().map_or(false, |target| { - assignment_is_cast_expr(value, target, self.context) - }) { + if targets + .first() + .is_some_and(|target| assignment_is_cast_expr(value, target, self.context)) + { return; } self.assignment_targets.extend( @@ -216,8 +213,7 @@ impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { // Decide whether to recurse. match stmt { // Don't recurse into blocks that create a new scope. - Stmt::ClassDef(_) => {} - Stmt::FunctionDef(_) => {} + Stmt::ClassDef(_) | Stmt::FunctionDef(_) => {} // Otherwise, do recurse. _ => { walk_stmt(self, stmt); @@ -236,7 +232,12 @@ impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { /// x = cast(int, x) /// ``` fn assignment_is_cast_expr(value: &Expr, target: &Expr, semantic: &SemanticModel) -> bool { - let Expr::Call(ast::ExprCall { func, args, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) = value + else { return false; }; let Expr::Name(ast::ExprName { id: target_id, .. }) = target else { @@ -333,8 +334,7 @@ fn assignment_targets_from_assign_targets<'a>( /// PLW2901 pub(crate) fn redefined_loop_name(checker: &mut Checker, stmt: &Stmt) { let (outer_assignment_targets, inner_assignment_targets) = match stmt { - Stmt::With(ast::StmtWith { items, body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { let outer_assignment_targets: Vec = assignment_targets_from_with_items(items, &checker.settings.dummy_variable_rgx) .map(|expr| ExprWithOuterBindingKind { @@ -352,8 +352,7 @@ pub(crate) fn redefined_loop_name(checker: &mut Checker, stmt: &Stmt) { } (outer_assignment_targets, visitor.assignment_targets) } - Stmt::For(ast::StmtFor { target, body, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, .. }) => { + Stmt::For(ast::StmtFor { target, body, .. }) => { let outer_assignment_targets: Vec = assignment_targets_from_expr(target, &checker.settings.dummy_variable_rgx) .map(|expr| ExprWithOuterBindingKind { @@ -371,9 +370,7 @@ pub(crate) fn redefined_loop_name(checker: &mut Checker, stmt: &Stmt) { } (outer_assignment_targets, visitor.assignment_targets) } - _ => panic!( - "redefined_loop_name called on Statement that is not a With, For, AsyncWith, or AsyncFor" - ) + _ => panic!("redefined_loop_name called on Statement that is not a `With` or `For`"), }; let mut diagnostics = Vec::new(); diff --git a/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs b/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs index 37d93751e84cf..a426c8e1ca7ba 100644 --- a/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs +++ b/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs @@ -2,14 +2,16 @@ use std::hash::BuildHasherDefault; use std::ops::Deref; use itertools::{any, Itertools}; -use ruff_python_ast::{BoolOp, CmpOp, Expr, ExprBoolOp, ExprCompare, Ranged}; use rustc_hash::FxHashMap; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::hashable::HashableExpr; +use ruff_python_ast::{self as ast, BoolOp, CmpOp, Expr, Ranged}; use ruff_source_file::Locator; +use crate::autofix::snippet::SourceCodeSnippet; use crate::checkers::ast::Checker; /// ## What it does @@ -42,21 +44,30 @@ use crate::checkers::ast::Checker; /// - [Python documentation: `set`](https://docs.python.org/3/library/stdtypes.html#set) #[violation] pub struct RepeatedEqualityComparisonTarget { - expr: String, + expression: SourceCodeSnippet, } impl Violation for RepeatedEqualityComparisonTarget { #[derive_message_formats] fn message(&self) -> String { - let RepeatedEqualityComparisonTarget { expr } = self; - format!( - "Consider merging multiple comparisons: `{expr}`. Use a `set` if the elements are hashable." - ) + let RepeatedEqualityComparisonTarget { expression } = self; + if let Some(expression) = expression.full_display() { + format!( + "Consider merging multiple comparisons: `{expression}`. Use a `set` if the elements are hashable." + ) + } else { + format!( + "Consider merging multiple comparisons. Use a `set` if the elements are hashable." + ) + } } } /// PLR1714 -pub(crate) fn repeated_equality_comparison_target(checker: &mut Checker, bool_op: &ExprBoolOp) { +pub(crate) fn repeated_equality_comparison_target( + checker: &mut Checker, + bool_op: &ast::ExprBoolOp, +) { if bool_op .values .iter() @@ -65,31 +76,53 @@ pub(crate) fn repeated_equality_comparison_target(checker: &mut Checker, bool_op return; } - let mut left_to_comparators: FxHashMap)> = - FxHashMap::with_capacity_and_hasher(bool_op.values.len(), BuildHasherDefault::default()); + let mut value_to_comparators: FxHashMap)> = + FxHashMap::with_capacity_and_hasher( + bool_op.values.len() * 2, + BuildHasherDefault::default(), + ); + for value in &bool_op.values { - if let Expr::Compare(ExprCompare { + // Enforced via `is_allowed_value`. + let Expr::Compare(ast::ExprCompare { left, comparators, .. }) = value - { - let (count, matches) = left_to_comparators + else { + return; + }; + + // Enforced via `is_allowed_value`. + let [right] = comparators.as_slice() else { + return; + }; + + if matches!(left.as_ref(), Expr::Name(_) | Expr::Attribute(_)) { + let (left_count, left_matches) = value_to_comparators .entry(left.deref().into()) .or_insert_with(|| (0, Vec::new())); - *count += 1; - matches.extend(comparators); + *left_count += 1; + left_matches.push(right); + } + + if matches!(right, Expr::Name(_) | Expr::Attribute(_)) { + let (right_count, right_matches) = value_to_comparators + .entry(right.into()) + .or_insert_with(|| (0, Vec::new())); + *right_count += 1; + right_matches.push(left); } } - for (left, (count, comparators)) in left_to_comparators { + for (value, (count, comparators)) in value_to_comparators { if count > 1 { checker.diagnostics.push(Diagnostic::new( RepeatedEqualityComparisonTarget { - expr: merged_membership_test( - left.as_expr(), + expression: SourceCodeSnippet::new(merged_membership_test( + value.as_expr(), bool_op.op, &comparators, checker.locator(), - ), + )), }, bool_op.range(), )); @@ -101,7 +134,7 @@ pub(crate) fn repeated_equality_comparison_target(checker: &mut Checker, bool_op /// E.g., `==` operators can be joined with `or` and `!=` operators can be /// joined with `and`. fn is_allowed_value(bool_op: BoolOp, value: &Expr) -> bool { - let Expr::Compare(ExprCompare { + let Expr::Compare(ast::ExprCompare { left, ops, comparators, @@ -111,24 +144,35 @@ fn is_allowed_value(bool_op: BoolOp, value: &Expr) -> bool { return false; }; - ops.iter().all(|op| { - if match bool_op { - BoolOp::Or => !matches!(op, CmpOp::Eq), - BoolOp::And => !matches!(op, CmpOp::NotEq), - } { - return false; - } + // Ignore, e.g., `foo == bar == baz`. + let [op] = ops.as_slice() else { + return false; + }; - if left.is_call_expr() { - return false; - } + if match bool_op { + BoolOp::Or => !matches!(op, CmpOp::Eq), + BoolOp::And => !matches!(op, CmpOp::NotEq), + } { + return false; + } - if any(comparators.iter(), Expr::is_call_expr) { - return false; - } + // Ignore self-comparisons, e.g., `foo == foo`. + let [right] = comparators.as_slice() else { + return false; + }; + if ComparableExpr::from(left) == ComparableExpr::from(right) { + return false; + } + + if left.is_call_expr() { + return false; + } + + if any(comparators.iter(), Expr::is_call_expr) { + return false; + } - true - }) + true } /// Generate a string like `obj in (a, b, c)` or `obj not in (a, b, c)`. diff --git a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs index 2923cc3b98c09..22e59a43d266f 100644 --- a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs +++ b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs @@ -1,5 +1,5 @@ use itertools::Itertools; -use ruff_python_ast::{self as ast, BoolOp, Expr, Ranged}; +use ruff_python_ast::{self as ast, Arguments, BoolOp, Expr, Ranged}; use rustc_hash::{FxHashMap, FxHashSet}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -73,7 +73,12 @@ pub(crate) fn repeated_isinstance_calls( let mut obj_to_types: FxHashMap)> = FxHashMap::default(); for value in values { - let Expr::Call(ast::ExprCall { func, args, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) = value + else { continue; }; if !matches!(func.as_ref(), Expr::Name(ast::ExprName { id, .. }) if id == "isinstance") { diff --git a/crates/ruff/src/rules/pylint/rules/self_assigning_variable.rs b/crates/ruff/src/rules/pylint/rules/self_assigning_variable.rs index fe54bb484e4d0..4176626a339dc 100644 --- a/crates/ruff/src/rules/pylint/rules/self_assigning_variable.rs +++ b/crates/ruff/src/rules/pylint/rules/self_assigning_variable.rs @@ -62,7 +62,7 @@ pub(crate) fn self_assigning_variable(checker: &mut Checker, target: &Expr, valu // Assignments in class bodies are attributes (e.g., `x = x` assigns `x` to `self.x`, and thus // is not a self-assignment). - if checker.semantic().scope().kind.is_class() { + if checker.semantic().current_scope().kind.is_class() { return; } diff --git a/crates/ruff/src/rules/pylint/rules/single_string_slots.rs b/crates/ruff/src/rules/pylint/rules/single_string_slots.rs index e4b51fd9cd7b7..82ba8bbbc9afb 100644 --- a/crates/ruff/src/rules/pylint/rules/single_string_slots.rs +++ b/crates/ruff/src/rules/pylint/rules/single_string_slots.rs @@ -70,7 +70,7 @@ pub(crate) fn single_string_slots(checker: &mut Checker, class: &StmtClassDef) { Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. - }) | Expr::JoinedStr(_) + }) | Expr::FString(_) ) { checker .diagnostics @@ -92,7 +92,7 @@ pub(crate) fn single_string_slots(checker: &mut Checker, class: &StmtClassDef) { Expr::Constant(ast::ExprConstant { value: Constant::Str(_), .. - }) | Expr::JoinedStr(_) + }) | Expr::FString(_) ) { checker .diagnostics diff --git a/crates/ruff/src/rules/pylint/rules/subprocess_popen_preexec_fn.rs b/crates/ruff/src/rules/pylint/rules/subprocess_popen_preexec_fn.rs index 847b2a23d381a..4094991b5adf6 100644 --- a/crates/ruff/src/rules/pylint/rules/subprocess_popen_preexec_fn.rs +++ b/crates/ruff/src/rules/pylint/rules/subprocess_popen_preexec_fn.rs @@ -1,7 +1,7 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_none}; -use ruff_python_ast::{Expr, Keyword, Ranged}; +use ruff_python_ast::helpers::is_const_none; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; @@ -48,16 +48,16 @@ impl Violation for SubprocessPopenPreexecFn { } /// PLW1509 -pub(crate) fn subprocess_popen_preexec_fn(checker: &mut Checker, func: &Expr, kwargs: &[Keyword]) { +pub(crate) fn subprocess_popen_preexec_fn(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["subprocess", "Popen"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "Popen"])) { - if let Some(keyword) = - find_keyword(kwargs, "preexec_fn").filter(|keyword| !is_const_none(&keyword.value)) + if let Some(keyword) = call + .arguments + .find_keyword("preexec_fn") + .filter(|keyword| !is_const_none(&keyword.value)) { checker .diagnostics diff --git a/crates/ruff/src/rules/pylint/rules/subprocess_run_without_check.rs b/crates/ruff/src/rules/pylint/rules/subprocess_run_without_check.rs new file mode 100644 index 0000000000000..f147e8446c270 --- /dev/null +++ b/crates/ruff/src/rules/pylint/rules/subprocess_run_without_check.rs @@ -0,0 +1,65 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast as ast; +use ruff_python_ast::Ranged; + +use crate::checkers::ast::Checker; + +/// ## What it does +/// Checks for uses of `subprocess.run` without an explicit `check` argument. +/// +/// ## Why is this bad? +/// By default, `subprocess.run` does not check the return code of the process +/// it runs. This can lead to silent failures. +/// +/// Instead, consider using `check=True` to raise an exception if the process +/// fails, or set `check=False` explicitly to mark the behavior as intentional. +/// +/// ## Example +/// ```python +/// import subprocess +/// +/// subprocess.run(["ls", "nonexistent"]) # No exception raised. +/// ``` +/// +/// Use instead: +/// ```python +/// import subprocess +/// +/// subprocess.run(["ls", "nonexistent"], check=True) # Raises exception. +/// ``` +/// +/// Or: +/// ```python +/// import subprocess +/// +/// subprocess.run(["ls", "nonexistent"], check=False) # Explicitly no check. +/// ``` +/// +/// ## References +/// - [Python documentation: `subprocess.run`](https://docs.python.org/3/library/subprocess.html#subprocess.run) +#[violation] +pub struct SubprocessRunWithoutCheck; + +impl Violation for SubprocessRunWithoutCheck { + #[derive_message_formats] + fn message(&self) -> String { + format!("`subprocess.run` without explicit `check` argument") + } +} + +/// PLW1510 +pub(crate) fn subprocess_run_without_check(checker: &mut Checker, call: &ast::ExprCall) { + if checker + .semantic() + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "run"])) + { + if call.arguments.find_keyword("check").is_none() { + checker.diagnostics.push(Diagnostic::new( + SubprocessRunWithoutCheck, + call.func.range(), + )); + } + } +} diff --git a/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs b/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs index f74965b5a1ca9..8948aeb0cc152 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_arguments.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Arguments, Stmt}; +use ruff_python_ast::{Parameters, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -10,7 +10,7 @@ use crate::checkers::ast::Checker; /// Checks for function definitions that include too many arguments. /// /// By default, this rule allows up to five arguments, as configured by the -/// `pylint.max-args` option. +/// [`pylint.max-args`] option. /// /// ## Why is this bad? /// Functions with many arguments are harder to understand, maintain, and call. @@ -58,13 +58,18 @@ impl Violation for TooManyArguments { } /// PLR0913 -pub(crate) fn too_many_arguments(checker: &mut Checker, arguments: &Arguments, stmt: &Stmt) { - let num_arguments = arguments +pub(crate) fn too_many_arguments(checker: &mut Checker, parameters: &Parameters, stmt: &Stmt) { + let num_arguments = parameters .args .iter() - .chain(&arguments.kwonlyargs) - .chain(&arguments.posonlyargs) - .filter(|arg| !checker.settings.dummy_variable_rgx.is_match(&arg.def.arg)) + .chain(¶meters.kwonlyargs) + .chain(¶meters.posonlyargs) + .filter(|arg| { + !checker + .settings + .dummy_variable_rgx + .is_match(&arg.parameter.name) + }) .count(); if num_arguments > checker.settings.pylint.max_args { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/pylint/rules/too_many_branches.rs b/crates/ruff/src/rules/pylint/rules/too_many_branches.rs index 466cb3e47a704..7c083b10f7654 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_branches.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_branches.rs @@ -8,7 +8,7 @@ use ruff_python_ast::identifier::Identifier; /// Checks for functions or methods with too many branches. /// /// By default, this rule allows up to 12 branches. This can be configured -/// using the `max-branches` option. +/// using the [`pylint.max-branches`] option. /// /// ## Why is this bad? /// Functions or methods with many branches are harder to understand @@ -66,8 +66,8 @@ use ruff_python_ast::identifier::Identifier; /// return city /// ``` /// -/// ## References -/// - [Ruff configuration documentation](https://beta.ruff.rs/docs/settings/#max-branches) +/// ## Options +/// - `pylint.max-branches` #[violation] pub struct TooManyBranches { branches: usize, @@ -108,7 +108,6 @@ fn num_branches(stmts: &[Stmt]) -> usize { .sum::() } Stmt::For(ast::StmtFor { body, orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) | Stmt::While(ast::StmtWhile { body, orelse, .. }) => { 1 + num_branches(body) + (if orelse.is_empty() { @@ -122,14 +121,7 @@ fn num_branches(stmts: &[Stmt]) -> usize { handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { 1 + num_branches(body) + (if orelse.is_empty() { @@ -183,13 +175,12 @@ pub(crate) fn too_many_branches( #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::Suite; - use ruff_python_parser::Parse; + use ruff_python_parser::parse_suite; use super::num_branches; fn test_helper(source: &str, expected_num_branches: usize) -> Result<()> { - let branches = Suite::parse(source, "")?; + let branches = parse_suite(source, "")?; assert_eq!(num_branches(&branches), expected_num_branches); Ok(()) } diff --git a/crates/ruff/src/rules/pylint/rules/too_many_return_statements.rs b/crates/ruff/src/rules/pylint/rules/too_many_return_statements.rs index 0a1c4f40fd050..8fc7fe16e6134 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_return_statements.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_return_statements.rs @@ -10,7 +10,7 @@ use ruff_python_ast::statement_visitor::StatementVisitor; /// Checks for functions or methods with too many return statements. /// /// By default, this rule allows up to six return statements, as configured by -/// the `pylint.max-returns` option. +/// the [`pylint.max-returns`] option. /// /// ## Why is this bad? /// Functions or methods with many return statements are harder to understand @@ -98,13 +98,12 @@ pub(crate) fn too_many_return_statements( #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::Suite; - use ruff_python_parser::Parse; + use ruff_python_parser::parse_suite; use super::num_returns; fn test_helper(source: &str, expected: usize) -> Result<()> { - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_returns(&stmts), expected); Ok(()) } diff --git a/crates/ruff/src/rules/pylint/rules/too_many_statements.rs b/crates/ruff/src/rules/pylint/rules/too_many_statements.rs index 3863c251e7bdb..406f5959fc33a 100644 --- a/crates/ruff/src/rules/pylint/rules/too_many_statements.rs +++ b/crates/ruff/src/rules/pylint/rules/too_many_statements.rs @@ -8,7 +8,7 @@ use ruff_python_ast::identifier::Identifier; /// Checks for functions or methods with too many statements. /// /// By default, this rule allows up to 50 statements, as configured by the -/// `pylint.max-statements` option. +/// [`pylint.max-statements`] option. /// /// ## Why is this bad? /// Functions or methods with many statements are harder to understand @@ -78,8 +78,7 @@ fn num_statements(stmts: &[Stmt]) -> usize { count += num_statements(&clause.body); } } - Stmt::For(ast::StmtFor { body, orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { + Stmt::For(ast::StmtFor { body, orelse, .. }) => { count += num_statements(body); count += num_statements(orelse); } @@ -99,14 +98,7 @@ fn num_statements(stmts: &[Stmt]) -> usize { handlers, orelse, finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, + .. }) => { count += 1; count += num_statements(body); @@ -129,7 +121,6 @@ fn num_statements(stmts: &[Stmt]) -> usize { } } Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) | Stmt::With(ast::StmtWith { body, .. }) => { count += 1; count += num_statements(body); @@ -166,8 +157,7 @@ pub(crate) fn too_many_statements( #[cfg(test)] mod tests { use anyhow::Result; - use ruff_python_ast::Suite; - use ruff_python_parser::Parse; + use ruff_python_parser::parse_suite; use super::num_statements; @@ -177,7 +167,7 @@ mod tests { def f(): pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 2); Ok(()) } @@ -191,7 +181,7 @@ def f(): else: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 5); Ok(()) } @@ -206,7 +196,7 @@ def f(): if a: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 6); Ok(()) } @@ -220,7 +210,7 @@ def f(): elif a: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 5); Ok(()) } @@ -238,7 +228,7 @@ def f(): else: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 9); Ok(()) } @@ -267,7 +257,7 @@ async def f(): import time pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 19); Ok(()) } @@ -279,7 +269,7 @@ def f(): for i in range(10): pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 2); Ok(()) } @@ -293,7 +283,7 @@ def f(): else: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 3); Ok(()) } @@ -308,7 +298,7 @@ def f(): print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 5); Ok(()) } @@ -326,7 +316,7 @@ def f(): print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 3); Ok(()) } @@ -337,7 +327,7 @@ def f(): def f(): return "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 1); Ok(()) } @@ -353,7 +343,7 @@ def f(): print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 6); Ok(()) } @@ -367,7 +357,7 @@ def f(): except Exception: raise "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 5); Ok(()) } @@ -383,7 +373,7 @@ def f(): else: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 7); Ok(()) } @@ -401,7 +391,7 @@ def f(): finally: pass "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 10); Ok(()) } @@ -417,7 +407,7 @@ def f(): except Exception: raise "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 8); Ok(()) } @@ -435,7 +425,7 @@ def f(): finally: print() "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 11); Ok(()) } @@ -447,7 +437,7 @@ def f(): for i in range(10): yield i "#; - let stmts = Suite::parse(source, "")?; + let stmts = parse_suite(source, "")?; assert_eq!(num_statements(&stmts), 2); Ok(()) } diff --git a/crates/ruff/src/rules/pylint/rules/type_bivariance.rs b/crates/ruff/src/rules/pylint/rules/type_bivariance.rs index 0227a8f46b2e0..fdeefdad7992f 100644 --- a/crates/ruff/src/rules/pylint/rules/type_bivariance.rs +++ b/crates/ruff/src/rules/pylint/rules/type_bivariance.rs @@ -1,10 +1,9 @@ use std::fmt; -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_true}; +use ruff_python_ast::helpers::is_const_true; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::rules::pylint::helpers::type_param_name; @@ -75,20 +74,22 @@ impl Violation for TypeBivariance { /// PLC0131 pub(crate) fn type_bivariance(checker: &mut Checker, value: &Expr) { let Expr::Call(ast::ExprCall { - func, - args, - keywords, - .. + func, arguments, .. }) = value else { return; }; - let Some(covariant) = find_keyword(keywords, "covariant").map(|keyword| &keyword.value) else { + let Some(covariant) = arguments + .find_keyword("covariant") + .map(|keyword| &keyword.value) + else { return; }; - let Some(contravariant) = find_keyword(keywords, "contravariant").map(|keyword| &keyword.value) + let Some(contravariant) = arguments + .find_keyword("contravariant") + .map(|keyword| &keyword.value) else { return; }; @@ -119,7 +120,7 @@ pub(crate) fn type_bivariance(checker: &mut Checker, value: &Expr) { checker.diagnostics.push(Diagnostic::new( TypeBivariance { kind, - param_name: type_param_name(args, keywords).map(ToString::to_string), + param_name: type_param_name(arguments).map(ToString::to_string), }, func.range(), )); diff --git a/crates/ruff/src/rules/pylint/rules/type_name_incorrect_variance.rs b/crates/ruff/src/rules/pylint/rules/type_name_incorrect_variance.rs index 75c89a35a288c..c4ddf8976333b 100644 --- a/crates/ruff/src/rules/pylint/rules/type_name_incorrect_variance.rs +++ b/crates/ruff/src/rules/pylint/rules/type_name_incorrect_variance.rs @@ -1,10 +1,9 @@ use std::fmt; -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_const_true}; +use ruff_python_ast::helpers::is_const_true; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::rules::pylint::helpers::type_param_name; @@ -66,22 +65,23 @@ impl Violation for TypeNameIncorrectVariance { /// PLC0105 pub(crate) fn type_name_incorrect_variance(checker: &mut Checker, value: &Expr) { let Expr::Call(ast::ExprCall { - func, - args, - keywords, - .. + func, arguments, .. }) = value else { return; }; - let Some(param_name) = type_param_name(args, keywords) else { + let Some(param_name) = type_param_name(arguments) else { return; }; - let covariant = find_keyword(keywords, "covariant").map(|keyword| &keyword.value); + let covariant = arguments + .find_keyword("covariant") + .map(|keyword| &keyword.value); - let contravariant = find_keyword(keywords, "contravariant").map(|keyword| &keyword.value); + let contravariant = arguments + .find_keyword("contravariant") + .map(|keyword| &keyword.value); if !mismatch(param_name, covariant, contravariant) { return; @@ -138,7 +138,7 @@ fn mismatch(param_name: &str, covariant: Option<&Expr>, contravariant: Option<&E } else if param_name.ends_with("_contra") { contravariant.map_or(true, |contravariant| !is_const_true(contravariant)) } else { - covariant.map_or(false, is_const_true) || contravariant.map_or(false, is_const_true) + covariant.is_some_and(is_const_true) || contravariant.is_some_and(is_const_true) } } diff --git a/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs b/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs index 0c240b0c9cf96..31db9780d7ea4 100644 --- a/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs +++ b/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs @@ -1,9 +1,8 @@ use std::fmt; -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::rules::pylint::helpers::type_param_name; @@ -68,16 +67,13 @@ pub(crate) fn type_param_name_mismatch(checker: &mut Checker, value: &Expr, targ }; let Expr::Call(ast::ExprCall { - func, - args, - keywords, - .. + func, arguments, .. }) = value else { return; }; - let Some(param_name) = type_param_name(args, keywords) else { + let Some(param_name) = type_param_name(arguments) else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs b/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs index 53ae9acf42c08..09182ef38461e 100644 --- a/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs +++ b/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; -use ruff_python_ast::{Arguments, Decorator, Stmt}; +use ruff_python_ast::{Decorator, Parameters, Stmt}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -141,24 +141,31 @@ pub(crate) fn unexpected_special_method_signature( stmt: &Stmt, name: &str, decorator_list: &[Decorator], - args: &Arguments, + parameters: &Parameters, ) { - if !checker.semantic().scope().kind.is_class() { + if !checker.semantic().current_scope().kind.is_class() { return; } // Ignore methods with positional-only or keyword-only parameters, or variadic parameters. - if !args.posonlyargs.is_empty() || !args.kwonlyargs.is_empty() || args.kwarg.is_some() { + if !parameters.posonlyargs.is_empty() + || !parameters.kwonlyargs.is_empty() + || parameters.kwarg.is_some() + { return; } // Method has no parameter, will be caught by no-method-argument (E0211/N805). - if args.args.is_empty() && args.vararg.is_none() { + if parameters.args.is_empty() && parameters.vararg.is_none() { return; } - let actual_params = args.args.len(); - let mandatory_params = args.args.iter().filter(|arg| arg.default.is_none()).count(); + let actual_params = parameters.args.len(); + let mandatory_params = parameters + .args + .iter() + .filter(|arg| arg.default.is_none()) + .count(); let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(decorator_list, checker.semantic())) @@ -171,12 +178,12 @@ pub(crate) fn unexpected_special_method_signature( if mandatory_params >= min { mandatory_params <= max } else { - args.vararg.is_some() || actual_params <= max + parameters.vararg.is_some() || actual_params <= max } } ExpectedParams::Fixed(expected) => match expected.cmp(&mandatory_params) { Ordering::Less => false, - Ordering::Greater => args.vararg.is_some() || actual_params >= expected, + Ordering::Greater => parameters.vararg.is_some() || actual_params >= expected, Ordering::Equal => true, }, }; diff --git a/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs b/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs index 00b0caad33348..ff354860c5cc3 100644 --- a/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs +++ b/crates/ruff/src/rules/pylint/rules/useless_else_on_loop.rs @@ -63,8 +63,7 @@ fn loop_exits_early(body: &[Stmt]) -> bool { .iter() .any(|clause| loop_exits_early(&clause.body)) } - Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => loop_exits_early(body), + Stmt::With(ast::StmtWith { body, .. }) => loop_exits_early(body), Stmt::Match(ast::StmtMatch { cases, .. }) => cases .iter() .any(|MatchCase { body, .. }| loop_exits_early(body)), @@ -74,13 +73,6 @@ fn loop_exits_early(body: &[Stmt]) -> bool { orelse, finalbody, .. - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - .. }) => { loop_exits_early(body) || loop_exits_early(orelse) @@ -91,9 +83,9 @@ fn loop_exits_early(body: &[Stmt]) -> bool { }) => loop_exits_early(body), }) } - Stmt::For(ast::StmtFor { orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { orelse, .. }) - | Stmt::While(ast::StmtWhile { orelse, .. }) => loop_exits_early(orelse), + Stmt::For(ast::StmtFor { orelse, .. }) | Stmt::While(ast::StmtWhile { orelse, .. }) => { + loop_exits_early(orelse) + } Stmt::Break(_) => true, _ => false, }) diff --git a/crates/ruff/src/rules/pylint/rules/useless_return.rs b/crates/ruff/src/rules/pylint/rules/useless_return.rs index d38cf9ae39c29..eaa8be21c65d8 100644 --- a/crates/ruff/src/rules/pylint/rules/useless_return.rs +++ b/crates/ruff/src/rules/pylint/rules/useless_return.rs @@ -109,7 +109,9 @@ pub(crate) fn useless_return( checker.locator(), checker.indexer(), ); - diagnostic.set_fix(Fix::automatic(edit).isolate(checker.isolation(Some(stmt)))); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation(Some( + checker.semantic().current_statement_id(), + )))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/pylint/rules/yield_from_in_async_function.rs b/crates/ruff/src/rules/pylint/rules/yield_from_in_async_function.rs index 5ed24e994ab4c..a94f388a03691 100644 --- a/crates/ruff/src/rules/pylint/rules/yield_from_in_async_function.rs +++ b/crates/ruff/src/rules/pylint/rules/yield_from_in_async_function.rs @@ -1,7 +1,7 @@ -use ruff_python_ast::{ExprYieldFrom, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Ranged}; +use ruff_python_semantic::ScopeKind; use crate::checkers::ast::Checker; @@ -37,9 +37,11 @@ impl Violation for YieldFromInAsyncFunction { } /// PLE1700 -pub(crate) fn yield_from_in_async_function(checker: &mut Checker, expr: &ExprYieldFrom) { - let scope = checker.semantic().scope(); - if scope.kind.is_async_function() { +pub(crate) fn yield_from_in_async_function(checker: &mut Checker, expr: &ast::ExprYieldFrom) { + if matches!( + checker.semantic().current_scope().kind, + ScopeKind::Function(ast::StmtFunctionDef { is_async: true, .. }) + ) { checker .diagnostics .push(Diagnostic::new(YieldFromInAsyncFunction, expr.range())); diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1300_bad_string_format_character.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1300_bad_string_format_character.py.snap new file mode 100644 index 0000000000000..709c8ec814c89 --- /dev/null +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1300_bad_string_format_character.py.snap @@ -0,0 +1,64 @@ +--- +source: crates/ruff/src/rules/pylint/mod.rs +--- +bad_string_format_character.py:5:1: PLE1300 Unsupported format character 'z' + | +3 | ## Old style formatting +4 | +5 | "%s %z" % ("hello", "world") # [bad-format-character] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +6 | +7 | "%s" "%z" % ("hello", "world") # [bad-format-character] + | + +bad_string_format_character.py:7:1: PLE1300 Unsupported format character 'z' + | +5 | "%s %z" % ("hello", "world") # [bad-format-character] +6 | +7 | "%s" "%z" % ("hello", "world") # [bad-format-character] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +8 | +9 | """%s %z""" % ("hello", "world") # [bad-format-character] + | + +bad_string_format_character.py:9:1: PLE1300 Unsupported format character 'z' + | + 7 | "%s" "%z" % ("hello", "world") # [bad-format-character] + 8 | + 9 | """%s %z""" % ("hello", "world") # [bad-format-character] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +10 | +11 | """%s""" """%z""" % ("hello", "world") # [bad-format-character] + | + +bad_string_format_character.py:11:1: PLE1300 Unsupported format character 'z' + | + 9 | """%s %z""" % ("hello", "world") # [bad-format-character] +10 | +11 | """%s""" """%z""" % ("hello", "world") # [bad-format-character] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +12 | +13 | ## New style formatting + | + +bad_string_format_character.py:15:1: PLE1300 Unsupported format character 'y' + | +13 | ## New style formatting +14 | +15 | "{:s} {:y}".format("hello", "world") # [bad-format-character] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +16 | +17 | "{:*^30s}".format("centered") # OK + | + +bad_string_format_character.py:19:1: PLE1300 Unsupported format character 'y' + | +17 | "{:*^30s}".format("centered") # OK +18 | "{:{s}}".format("hello", s="s") # OK (nested placeholder value not checked) +19 | "{:{s:y}}".format("hello", s="s") # [bad-format-character] (nested placeholder format spec checked) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1300 +20 | "{0:.{prec}g}".format(1.23, prec=15) # OK (cannot validate after nested placeholder) +21 | "{0:.{foo}{bar}{foobar}y}".format(...) # OK (cannot validate after nested placeholders) + | + + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1307_bad_string_format_type.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1307_bad_string_format_type.py.snap index a0366a476ba51..e50006d76397e 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1307_bad_string_format_type.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1307_bad_string_format_type.py.snap @@ -69,6 +69,16 @@ bad_string_format_type.py:10:1: PLE1307 Format type does not match argument type 12 | "%d" % ([],) | +bad_string_format_type.py:11:1: PLE1307 Format type does not match argument type + | + 9 | "%x" % 1.1 +10 | "%(key)x" % {"key": 1.1} +11 | "%d" % [] + | ^^^^^^^^^ PLE1307 +12 | "%d" % ([],) +13 | "%(key)d" % {"key": []} + | + bad_string_format_type.py:12:1: PLE1307 Format type does not match argument type | 10 | "%(key)x" % {"key": 1.1} @@ -96,6 +106,7 @@ bad_string_format_type.py:14:7: PLE1307 Format type does not match argument type 14 | print("%d" % ("%s" % ("nested",),)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1307 15 | "%d" % ((1, 2, 3),) +16 | "%d" % (1 if x > 0 else []) | bad_string_format_type.py:15:1: PLE1307 Format type does not match argument type @@ -104,8 +115,17 @@ bad_string_format_type.py:15:1: PLE1307 Format type does not match argument type 14 | print("%d" % ("%s" % ("nested",),)) 15 | "%d" % ((1, 2, 3),) | ^^^^^^^^^^^^^^^^^^^ PLE1307 -16 | -17 | # False negatives +16 | "%d" % (1 if x > 0 else []) + | + +bad_string_format_type.py:16:1: PLE1307 Format type does not match argument type + | +14 | print("%d" % ("%s" % ("nested",),)) +15 | "%d" % ((1, 2, 3),) +16 | "%d" % (1 if x > 0 else []) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1307 +17 | +18 | # False negatives | diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1507_invalid_envvar_value.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1507_invalid_envvar_value.py.snap index 1e8c0a24dd97d..6564ff6dd041a 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1507_invalid_envvar_value.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1507_invalid_envvar_value.py.snap @@ -37,8 +37,18 @@ invalid_envvar_value.py:12:15: PLE1507 Invalid type for initial `os.getenv` argu 11 | os.getenv(key="foo" + "bar", default=1) 12 | os.getenv(key=1 + "bar", default=1) # [invalid-envvar-value] | ^^^^^^^^^ PLE1507 -13 | -14 | AA = "aa" +13 | os.getenv("PATH_TEST" if using_clear_path else "PATH_ORIG") +14 | os.getenv(1 if using_clear_path else "PATH_ORIG") + | + +invalid_envvar_value.py:14:11: PLE1507 Invalid type for initial `os.getenv` argument; expected `str` + | +12 | os.getenv(key=1 + "bar", default=1) # [invalid-envvar-value] +13 | os.getenv("PATH_TEST" if using_clear_path else "PATH_ORIG") +14 | os.getenv(1 if using_clear_path else "PATH_ORIG") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLE1507 +15 | +16 | AA = "aa" | diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0124_comparison_with_itself.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0124_comparison_with_itself.py.snap index 3fffdeb481f63..711834227e64a 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0124_comparison_with_itself.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0124_comparison_with_itself.py.snap @@ -97,7 +97,27 @@ comparison_with_itself.py:20:1: PLR0124 Name compared with itself, consider repl 20 | foo not in foo | ^^^ PLR0124 21 | -22 | # Non-errors. +22 | id(foo) == id(foo) + | + +comparison_with_itself.py:22:1: PLR0124 Name compared with itself, consider replacing `id(foo) == id(foo)` + | +20 | foo not in foo +21 | +22 | id(foo) == id(foo) + | ^^^^^^^ PLR0124 +23 | +24 | len(foo) == len(foo) + | + +comparison_with_itself.py:24:1: PLR0124 Name compared with itself, consider replacing `len(foo) == len(foo)` + | +22 | id(foo) == id(foo) +23 | +24 | len(foo) == len(foo) + | ^^^^^^^^ PLR0124 +25 | +26 | # Non-errors. | diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1714_repeated_equality_comparison_target.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1714_repeated_equality_comparison_target.py.snap index 9fa0ddc667a4b..40373cea07ca5 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1714_repeated_equality_comparison_target.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1714_repeated_equality_comparison_target.py.snap @@ -47,7 +47,97 @@ repeated_equality_comparison_target.py:10:1: PLR1714 Consider merging multiple c 10 | foo == a or foo == "b" or foo == 3 # Mixed types. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 11 | -12 | # False negatives (the current implementation doesn't support Yoda conditions). +12 | "a" == foo or "b" == foo or "c" == foo + | + +repeated_equality_comparison_target.py:12:1: PLR1714 Consider merging multiple comparisons: `foo in ("a", "b", "c")`. Use a `set` if the elements are hashable. + | +10 | foo == a or foo == "b" or foo == 3 # Mixed types. +11 | +12 | "a" == foo or "b" == foo or "c" == foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +13 | +14 | "a" != foo and "b" != foo and "c" != foo + | + +repeated_equality_comparison_target.py:14:1: PLR1714 Consider merging multiple comparisons: `foo not in ("a", "b", "c")`. Use a `set` if the elements are hashable. + | +12 | "a" == foo or "b" == foo or "c" == foo +13 | +14 | "a" != foo and "b" != foo and "c" != foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +15 | +16 | "a" == foo or foo == "b" or "c" == foo + | + +repeated_equality_comparison_target.py:16:1: PLR1714 Consider merging multiple comparisons: `foo in ("a", "b", "c")`. Use a `set` if the elements are hashable. + | +14 | "a" != foo and "b" != foo and "c" != foo +15 | +16 | "a" == foo or foo == "b" or "c" == foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +17 | +18 | foo == bar or baz == foo or qux == foo + | + +repeated_equality_comparison_target.py:18:1: PLR1714 Consider merging multiple comparisons: `foo in (bar, baz, qux)`. Use a `set` if the elements are hashable. + | +16 | "a" == foo or foo == "b" or "c" == foo +17 | +18 | foo == bar or baz == foo or qux == foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +19 | +20 | foo == "a" or "b" == foo or foo == "c" + | + +repeated_equality_comparison_target.py:20:1: PLR1714 Consider merging multiple comparisons: `foo in ("a", "b", "c")`. Use a `set` if the elements are hashable. + | +18 | foo == bar or baz == foo or qux == foo +19 | +20 | foo == "a" or "b" == foo or foo == "c" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +21 | +22 | foo != "a" and "b" != foo and foo != "c" + | + +repeated_equality_comparison_target.py:22:1: PLR1714 Consider merging multiple comparisons: `foo not in ("a", "b", "c")`. Use a `set` if the elements are hashable. + | +20 | foo == "a" or "b" == foo or foo == "c" +21 | +22 | foo != "a" and "b" != foo and foo != "c" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +23 | +24 | foo == "a" or foo == "b" or "c" == bar or "d" == bar # Multiple targets + | + +repeated_equality_comparison_target.py:24:1: PLR1714 Consider merging multiple comparisons: `foo in ("a", "b")`. Use a `set` if the elements are hashable. + | +22 | foo != "a" and "b" != foo and foo != "c" +23 | +24 | foo == "a" or foo == "b" or "c" == bar or "d" == bar # Multiple targets + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +25 | +26 | foo.bar == "a" or foo.bar == "b" # Attributes. + | + +repeated_equality_comparison_target.py:24:1: PLR1714 Consider merging multiple comparisons: `bar in ("c", "d")`. Use a `set` if the elements are hashable. + | +22 | foo != "a" and "b" != foo and foo != "c" +23 | +24 | foo == "a" or foo == "b" or "c" == bar or "d" == bar # Multiple targets + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +25 | +26 | foo.bar == "a" or foo.bar == "b" # Attributes. + | + +repeated_equality_comparison_target.py:26:1: PLR1714 Consider merging multiple comparisons: `foo.bar in ("a", "b")`. Use a `set` if the elements are hashable. + | +24 | foo == "a" or foo == "b" or "c" == bar or "d" == bar # Multiple targets +25 | +26 | foo.bar == "a" or foo.bar == "b" # Attributes. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLR1714 +27 | +28 | # OK | diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_11.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_11.py.snap new file mode 100644 index 0000000000000..ef9fc255fce69 --- /dev/null +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_11.py.snap @@ -0,0 +1,20 @@ +--- +source: crates/ruff/src/rules/pylint/mod.rs +--- +sys_exit_alias_11.py:3:1: PLR1722 [*] Use `sys.exit()` instead of `exit` + | +1 | from sys import * +2 | +3 | exit(0) + | ^^^^ PLR1722 + | + = help: Replace `exit` with `sys.exit()` + +ℹ Suggested fix +1 1 | from sys import * + 2 |+import sys +2 3 | +3 |-exit(0) + 4 |+sys.exit(0) + + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_5.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_5.py.snap index 65ce946ce8e08..8bc6c5f88903d 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_5.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR1722_sys_exit_alias_5.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff/src/rules/pylint/mod.rs --- -sys_exit_alias_5.py:3:1: PLR1722 Use `sys.exit()` instead of `exit` +sys_exit_alias_5.py:3:1: PLR1722 [*] Use `sys.exit()` instead of `exit` | 1 | from sys import * 2 | @@ -11,7 +11,17 @@ sys_exit_alias_5.py:3:1: PLR1722 Use `sys.exit()` instead of `exit` | = help: Replace `exit` with `sys.exit()` -sys_exit_alias_5.py:4:1: PLR1722 Use `sys.exit()` instead of `quit` +ℹ Suggested fix +1 1 | from sys import * + 2 |+import sys +2 3 | +3 |-exit(0) + 4 |+sys.exit(0) +4 5 | quit(0) +5 6 | +6 7 | + +sys_exit_alias_5.py:4:1: PLR1722 [*] Use `sys.exit()` instead of `quit` | 3 | exit(0) 4 | quit(0) @@ -19,7 +29,18 @@ sys_exit_alias_5.py:4:1: PLR1722 Use `sys.exit()` instead of `quit` | = help: Replace `quit` with `sys.exit()` -sys_exit_alias_5.py:8:5: PLR1722 Use `sys.exit()` instead of `exit` +ℹ Suggested fix +1 1 | from sys import * + 2 |+import sys +2 3 | +3 4 | exit(0) +4 |-quit(0) + 5 |+sys.exit(0) +5 6 | +6 7 | +7 8 | def main(): + +sys_exit_alias_5.py:8:5: PLR1722 [*] Use `sys.exit()` instead of `exit` | 7 | def main(): 8 | exit(1) @@ -28,7 +49,20 @@ sys_exit_alias_5.py:8:5: PLR1722 Use `sys.exit()` instead of `exit` | = help: Replace `exit` with `sys.exit()` -sys_exit_alias_5.py:9:5: PLR1722 Use `sys.exit()` instead of `quit` +ℹ Suggested fix +1 1 | from sys import * + 2 |+import sys +2 3 | +3 4 | exit(0) +4 5 | quit(0) +5 6 | +6 7 | +7 8 | def main(): +8 |- exit(1) + 9 |+ sys.exit(1) +9 10 | quit(1) + +sys_exit_alias_5.py:9:5: PLR1722 [*] Use `sys.exit()` instead of `quit` | 7 | def main(): 8 | exit(1) @@ -37,4 +71,17 @@ sys_exit_alias_5.py:9:5: PLR1722 Use `sys.exit()` instead of `quit` | = help: Replace `quit` with `sys.exit()` +ℹ Suggested fix +1 1 | from sys import * + 2 |+import sys +2 3 | +3 4 | exit(0) +4 5 | quit(0) +-------------------------------------------------------------------------------- +6 7 | +7 8 | def main(): +8 9 | exit(1) +9 |- quit(1) + 10 |+ sys.exit(1) + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR6301_no_self_use.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR6301_no_self_use.py.snap new file mode 100644 index 0000000000000..b37e14286348d --- /dev/null +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR6301_no_self_use.py.snap @@ -0,0 +1,39 @@ +--- +source: crates/ruff/src/rules/pylint/mod.rs +--- +no_self_use.py:5:28: PLR6301 Method `developer_greeting` could be a function or static method + | +4 | class Person: +5 | def developer_greeting(self, name): # [no-self-use] + | ^^^^ PLR6301 +6 | print(f"Greetings {name}!") + | + +no_self_use.py:8:20: PLR6301 Method `greeting_1` could be a function or static method + | +6 | print(f"Greetings {name}!") +7 | +8 | def greeting_1(self): # [no-self-use] + | ^^^^ PLR6301 +9 | print("Hello!") + | + +no_self_use.py:11:20: PLR6301 Method `greeting_2` could be a function or static method + | + 9 | print("Hello!") +10 | +11 | def greeting_2(self): # [no-self-use] + | ^^^^ PLR6301 +12 | print("Hi!") + | + +no_self_use.py:55:25: PLR6301 Method `abstract_method` could be a function or static method + | +53 | class Sub(Base): +54 | @override +55 | def abstract_method(self): + | ^^^^ PLR6301 +56 | print("concret method") + | + + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1510_subprocess_run_without_check.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1510_subprocess_run_without_check.py.snap new file mode 100644 index 0000000000000..481f380608958 --- /dev/null +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1510_subprocess_run_without_check.py.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/pylint/mod.rs +--- +subprocess_run_without_check.py:4:1: PLW1510 `subprocess.run` without explicit `check` argument + | +3 | # Errors. +4 | subprocess.run("ls") + | ^^^^^^^^^^^^^^ PLW1510 +5 | subprocess.run("ls", shell=True) + | + +subprocess_run_without_check.py:5:1: PLW1510 `subprocess.run` without explicit `check` argument + | +3 | # Errors. +4 | subprocess.run("ls") +5 | subprocess.run("ls", shell=True) + | ^^^^^^^^^^^^^^ PLW1510 +6 | +7 | # Non-errors. + | + + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1641_eq_without_hash.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1641_eq_without_hash.py.snap index 83af186c0079b..5be273e060d01 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1641_eq_without_hash.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW1641_eq_without_hash.py.snap @@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pylint/mod.rs --- eq_without_hash.py:1:7: PLW1641 Object does not implement `__hash__` method | -1 | class Person: +1 | class Person: # [eq-without-hash] | ^^^^^^ PLW1641 2 | def __init__(self): 3 | self.name = "monty" diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3201_bad_dunder_method_name.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3201_bad_dunder_method_name.py.snap new file mode 100644 index 0000000000000..f3c6b8166115c --- /dev/null +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3201_bad_dunder_method_name.py.snap @@ -0,0 +1,61 @@ +--- +source: crates/ruff/src/rules/pylint/mod.rs +--- +bad_dunder_method_name.py:2:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name) + | +1 | class Apples: +2 | def _init_(self): # [bad-dunder-name] + | ^^^^^^ PLW3201 +3 | pass + | + +bad_dunder_method_name.py:5:9: PLW3201 Bad or misspelled dunder method name `__hello__`. (bad-dunder-name) + | +3 | pass +4 | +5 | def __hello__(self): # [bad-dunder-name] + | ^^^^^^^^^ PLW3201 +6 | print("hello") + | + +bad_dunder_method_name.py:8:9: PLW3201 Bad or misspelled dunder method name `__init_`. (bad-dunder-name) + | + 6 | print("hello") + 7 | + 8 | def __init_(self): # [bad-dunder-name] + | ^^^^^^^ PLW3201 + 9 | # author likely unintentionally misspelled the correct init dunder. +10 | pass + | + +bad_dunder_method_name.py:12:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name) + | +10 | pass +11 | +12 | def _init_(self): # [bad-dunder-name] + | ^^^^^^ PLW3201 +13 | # author likely unintentionally misspelled the correct init dunder. +14 | pass + | + +bad_dunder_method_name.py:16:9: PLW3201 Bad or misspelled dunder method name `___neg__`. (bad-dunder-name) + | +14 | pass +15 | +16 | def ___neg__(self): # [bad-dunder-name] + | ^^^^^^^^ PLW3201 +17 | # author likely accidentally added an additional `_` +18 | pass + | + +bad_dunder_method_name.py:20:9: PLW3201 Bad or misspelled dunder method name `__inv__`. (bad-dunder-name) + | +18 | pass +19 | +20 | def __inv__(self): # [bad-dunder-name] + | ^^^^^^^ PLW3201 +21 | # author likely meant to call the invert dunder method +22 | pass + | + + diff --git a/crates/ruff/src/rules/pyupgrade/fixes.rs b/crates/ruff/src/rules/pyupgrade/fixes.rs index 9c9d315db008d..648d644f3c43e 100644 --- a/crates/ruff/src/rules/pyupgrade/fixes.rs +++ b/crates/ruff/src/rules/pyupgrade/fixes.rs @@ -1,17 +1,12 @@ use anyhow::Result; -use libcst_native::ParenthesizableWhitespace; -use ruff_python_ast::{Expr, Ranged}; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::{TextRange, TextSize}; -use crate::autofix::codemods::CodegenStylist; -use ruff_diagnostics::Edit; use ruff_python_codegen::Stylist; +use ruff_python_parser::{lexer, Mode, Tok}; use ruff_source_file::Locator; +use ruff_text_size::{TextRange, TextSize}; -use crate::cst::matchers::{ - match_call_mut, match_expression, match_function_def, match_indented_block, match_statement, -}; +use crate::autofix::codemods::CodegenStylist; +use crate::cst::matchers::{match_function_def, match_indented_block, match_statement}; /// Safely adjust the indentation of the indented block at [`TextRange`]. pub(crate) fn adjust_indentation( @@ -39,29 +34,6 @@ pub(crate) fn adjust_indentation( Ok(module_text) } -/// Generate a fix to remove arguments from a `super` call. -pub(crate) fn remove_super_arguments( - locator: &Locator, - stylist: &Stylist, - expr: &Expr, -) -> Option { - let range = expr.range(); - let contents = locator.slice(range); - - let mut tree = match_expression(contents).ok()?; - - let body = match_call_mut(&mut tree).ok()?; - - body.args = vec![]; - body.whitespace_before_args = ParenthesizableWhitespace::default(); - body.whitespace_after_func = ParenthesizableWhitespace::default(); - - Some(Edit::range_replacement( - tree.codegen_stylist(stylist), - range, - )) -} - /// Remove any imports matching `members` from an import-from statement. pub(crate) fn remove_import_members(contents: &str, members: &[&str]) -> String { let mut names: Vec = vec![]; diff --git a/crates/ruff/src/rules/pyupgrade/mod.rs b/crates/ruff/src/rules/pyupgrade/mod.rs index 0ec3c25e4b7db..416972454fcc4 100644 --- a/crates/ruff/src/rules/pyupgrade/mod.rs +++ b/crates/ruff/src/rules/pyupgrade/mod.rs @@ -30,7 +30,6 @@ mod tests { #[test_case(Rule::FString, Path::new("UP032_2.py"))] #[test_case(Rule::FormatLiterals, Path::new("UP030_0.py"))] #[test_case(Rule::FormatLiterals, Path::new("UP030_1.py"))] - #[test_case(Rule::FormatLiterals, Path::new("UP030_2.py"))] #[test_case(Rule::LRUCacheWithMaxsizeNone, Path::new("UP033_0.py"))] #[test_case(Rule::LRUCacheWithMaxsizeNone, Path::new("UP033_1.py"))] #[test_case(Rule::LRUCacheWithoutParameters, Path::new("UP011.py"))] @@ -68,6 +67,11 @@ mod tests { #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_3.py"))] #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_4.py"))] #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_5.py"))] + #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_6.py"))] + #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_7.py"))] + #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_8.py"))] + #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_9.py"))] + #[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_10.py"))] #[test_case(Rule::UnicodeKindPrefix, Path::new("UP025.py"))] #[test_case(Rule::UnnecessaryBuiltinImport, Path::new("UP029.py"))] #[test_case(Rule::UnnecessaryClassParentheses, Path::new("UP039.py"))] @@ -78,6 +82,7 @@ mod tests { #[test_case(Rule::UselessObjectInheritance, Path::new("UP004.py"))] #[test_case(Rule::YieldInForLoop, Path::new("UP028_0.py"))] #[test_case(Rule::YieldInForLoop, Path::new("UP028_1.py"))] + #[test_case(Rule::NonPEP695TypeAlias, Path::new("UP040.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = path.to_string_lossy().to_string(); let diagnostics = test_path( @@ -88,6 +93,19 @@ mod tests { Ok(()) } + #[test] + fn non_pep695_type_alias_not_applied_py311() -> Result<()> { + let diagnostics = test_path( + Path::new("pyupgrade/UP040.py"), + &settings::Settings { + target_version: PythonVersion::Py311, + ..settings::Settings::for_rule(Rule::NonPEP695TypeAlias) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } + #[test] fn future_annotations_keep_runtime_typing_p37() -> Result<()> { let diagnostics = test_path( diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs index 22bb091d03be5..927716050f0ea 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use log::debug; use ruff_python_ast::{ - self as ast, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt, + self as ast, Arguments, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt, }; use ruff_text_size::TextRange; @@ -78,8 +78,7 @@ fn match_named_tuple_assign<'a>( }; let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: Arguments { args, keywords, .. }, range: _, }) = value else { @@ -91,7 +90,7 @@ fn match_named_tuple_assign<'a>( Some((typename, args, keywords, func)) } -/// Generate a `Stmt::AnnAssign` representing the provided property +/// Generate a [`Stmt::AnnAssign`] representing the provided property /// definition. fn create_property_assignment_stmt(property: &str, annotation: &Expr) -> Stmt { ast::StmtAnnAssign { @@ -131,7 +130,10 @@ fn create_properties_from_fields_arg(fields: &Expr) -> Result> { bail!("Expected `elts` to have exactly two elements") }; let Expr::Constant(ast::ExprConstant { - value: Constant::Str(property), + value: + Constant::Str(ast::StringConstant { + value: property, .. + }), .. }) = &field_name else { @@ -167,10 +169,13 @@ fn create_properties_from_keywords(keywords: &[Keyword]) -> Result> { fn create_class_def_stmt(typename: &str, body: Vec, base_class: &Expr) -> Stmt { ast::StmtClassDef { name: Identifier::new(typename.to_string(), TextRange::default()), - bases: vec![base_class.clone()], - keywords: vec![], + arguments: Some(Box::new(Arguments { + args: vec![base_class.clone()], + keywords: vec![], + range: TextRange::default(), + })), body, - type_params: vec![], + type_params: None, decorator_list: vec![], range: TextRange::default(), } diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs index b6b2f57d44d2a..6312bcaa86d86 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs @@ -1,16 +1,16 @@ use anyhow::{bail, Result}; use log::debug; -use ruff_python_ast::{ - self as ast, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt, -}; -use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::{find_keyword, is_dunder}; +use ruff_python_ast::helpers::is_dunder; +use ruff_python_ast::{ + self as ast, Arguments, Constant, Expr, ExprContext, Identifier, Keyword, Ranged, Stmt, +}; use ruff_python_codegen::Generator; use ruff_python_semantic::SemanticModel; use ruff_python_stdlib::identifiers::is_identifier; +use ruff_text_size::TextRange; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -70,15 +70,14 @@ fn match_typed_dict_assign<'a>( targets: &'a [Expr], value: &'a Expr, semantic: &SemanticModel, -) -> Option<(&'a str, &'a [Expr], &'a [Keyword], &'a Expr)> { +) -> Option<(&'a str, &'a Arguments, &'a Expr)> { let target = targets.get(0)?; let Expr::Name(ast::ExprName { id: class_name, .. }) = target else { return None; }; let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments, range: _, }) = value else { @@ -87,10 +86,10 @@ fn match_typed_dict_assign<'a>( if !semantic.match_typing_expr(func, "TypedDict") { return None; } - Some((class_name, args, keywords, func)) + Some((class_name, arguments, func)) } -/// Generate a `Stmt::AnnAssign` representing the provided property +/// Generate a [`Stmt::AnnAssign`] representing the provided property /// definition. fn create_property_assignment_stmt(property: &str, annotation: &Expr) -> Stmt { ast::StmtAnnAssign { @@ -118,16 +117,18 @@ fn create_class_def_stmt( total_keyword: Option<&Keyword>, base_class: &Expr, ) -> Stmt { - let keywords = match total_keyword { - Some(keyword) => vec![keyword.clone()], - None => vec![], - }; ast::StmtClassDef { name: Identifier::new(class_name.to_string(), TextRange::default()), - bases: vec![base_class.clone()], - keywords, + arguments: Some(Box::new(Arguments { + args: vec![base_class.clone()], + keywords: match total_keyword { + Some(keyword) => vec![keyword.clone()], + None => vec![], + }, + range: TextRange::default(), + })), body, - type_params: vec![], + type_params: None, decorator_list: vec![], range: TextRange::default(), } @@ -146,7 +147,10 @@ fn properties_from_dict_literal(keys: &[Option], values: &[Expr]) -> Resul .zip(values.iter()) .map(|(key, value)| match key { Some(Expr::Constant(ast::ExprConstant { - value: Constant::Str(property), + value: + Constant::Str(ast::StringConstant { + value: property, .. + }), .. })) => { if !is_identifier(property) { @@ -200,30 +204,29 @@ fn properties_from_keywords(keywords: &[Keyword]) -> Result> { .collect() } -fn match_properties_and_total<'a>( - args: &'a [Expr], - keywords: &'a [Keyword], -) -> Result<(Vec, Option<&'a Keyword>)> { +fn match_properties_and_total(arguments: &Arguments) -> Result<(Vec, Option<&Keyword>)> { // We don't have to manage the hybrid case because it's not possible to have a // dict and keywords. For example, the following is illegal: // ``` // MyType = TypedDict('MyType', {'a': int, 'b': str}, a=int, b=str) // ``` - if let Some(dict) = args.get(1) { - let total = find_keyword(keywords, "total"); + if let Some(dict) = arguments.args.get(1) { + let total = arguments.find_keyword("total"); match dict { Expr::Dict(ast::ExprDict { keys, values, range: _, }) => Ok((properties_from_dict_literal(keys, values)?, total)), - Expr::Call(ast::ExprCall { func, keywords, .. }) => { - Ok((properties_from_dict_call(func, keywords)?, total)) - } + Expr::Call(ast::ExprCall { + func, + arguments: Arguments { keywords, .. }, + .. + }) => Ok((properties_from_dict_call(func, keywords)?, total)), _ => bail!("Expected `arg` to be `Expr::Dict` or `Expr::Call`"), } - } else if !keywords.is_empty() { - Ok((properties_from_keywords(keywords)?, None)) + } else if !arguments.keywords.is_empty() { + Ok((properties_from_keywords(&arguments.keywords)?, None)) } else { let node = Stmt::Pass(ast::StmtPass { range: TextRange::default(), @@ -259,13 +262,13 @@ pub(crate) fn convert_typed_dict_functional_to_class( targets: &[Expr], value: &Expr, ) { - let Some((class_name, args, keywords, base_class)) = + let Some((class_name, arguments, base_class)) = match_typed_dict_assign(targets, value, checker.semantic()) else { return; }; - let (body, total_keyword) = match match_properties_and_total(args, keywords) { + let (body, total_keyword) = match match_properties_and_total(arguments) { Ok((body, total_keyword)) => (body, total_keyword), Err(err) => { debug!("Skipping ineligible `TypedDict` \"{class_name}\": {err}"); diff --git a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs index 7ab37ef3a6469..1f6e195ea7113 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs @@ -54,9 +54,7 @@ pub(crate) fn datetime_utc_alias(checker: &mut Checker, expr: &Expr) { if checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["datetime", "timezone", "utc"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "timezone", "utc"])) { let mut diagnostic = Diagnostic::new(DatetimeTimezoneUTC, expr.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs index 577d96b53f2ff..6d41e1aeb0c38 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs @@ -71,7 +71,7 @@ pub(crate) fn deprecated_c_element_tree(checker: &mut Checker, stmt: &Stmt) { level, range: _, }) => { - if level.map_or(false, |level| level.to_u32() > 0) { + if level.is_some_and(|level| level.to_u32() > 0) { // Ex) `import .xml.etree.cElementTree as ET` } else if let Some(module) = module { if module == "xml.etree.cElementTree" { diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs index 40adda66b3f50..6ec2ad0148b56 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs @@ -549,10 +549,10 @@ pub(crate) fn deprecated_import( level: Option, ) { // Avoid relative and star imports. - if level.map_or(false, |level| level > 0) { + if level.is_some_and(|level| level > 0) { return; } - if names.first().map_or(false, |name| &name.name == "*") { + if names.first().is_some_and(|name| &name.name == "*") { return; } let Some(module) = module else { diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs index 6920e7dbd11c7..08b1efffc93a8 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -251,9 +251,9 @@ fn format_import_from( /// UP026 pub(crate) fn deprecated_mock_attribute(checker: &mut Checker, expr: &Expr) { if let Expr::Attribute(ast::ExprAttribute { value, .. }) = expr { - if collect_call_path(value).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["mock", "mock"]) - }) { + if collect_call_path(value) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["mock", "mock"])) + { let mut diagnostic = Diagnostic::new( DeprecatedMockImport { reference_type: MockReference::Attribute, @@ -322,7 +322,7 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { level, .. }) => { - if level.map_or(false, |level| level.to_u32() > 0) { + if level.is_some_and(|level| level.to_u32() > 0) { return; } @@ -335,10 +335,10 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { ); if checker.patch(diagnostic.kind.rule()) { if let Some(indent) = indentation(checker.locator(), stmt) { - #[allow(deprecated)] - diagnostic.try_set_fix_from_edit(|| { + diagnostic.try_set_fix(|| { format_import_from(stmt, indent, checker.locator(), checker.stylist()) .map(|content| Edit::range_replacement(content, stmt.range())) + .map(Fix::suggested) }); } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs index f716a465bbb48..a939672f303b9 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs @@ -59,21 +59,21 @@ impl AlwaysAutofixableViolation for DeprecatedUnittestAlias { static DEPRECATED_ALIASES: Lazy> = Lazy::new(|| { FxHashMap::from_iter([ - ("failUnlessEqual", "assertEqual"), + ("assertAlmostEquals", "assertAlmostEqual"), ("assertEquals", "assertEqual"), - ("failIfEqual", "assertNotEqual"), + ("assertNotAlmostEquals", "assertNotAlmostEqual"), ("assertNotEquals", "assertNotEqual"), - ("failUnless", "assertTrue"), + ("assertNotRegexpMatches", "assertNotRegex"), + ("assertRaisesRegexp", "assertRaisesRegex"), + ("assertRegexpMatches", "assertRegex"), ("assert_", "assertTrue"), ("failIf", "assertFalse"), - ("failUnlessRaises", "assertRaises"), - ("failUnlessAlmostEqual", "assertAlmostEqual"), - ("assertAlmostEquals", "assertAlmostEqual"), ("failIfAlmostEqual", "assertNotAlmostEqual"), - ("assertNotAlmostEquals", "assertNotAlmostEqual"), - ("assertRegexpMatches", "assertRegex"), - ("assertNotRegexpMatches", "assertNotRegex"), - ("assertRaisesRegexp", "assertRaisesRegex"), + ("failIfEqual", "assertNotEqual"), + ("failUnless", "assertTrue"), + ("failUnlessAlmostEqual", "assertAlmostEqual"), + ("failUnlessEqual", "assertEqual"), + ("failUnlessRaises", "assertRaises"), ]) }); diff --git a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs index c5d3542f7f977..b086532130e45 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs @@ -1,16 +1,18 @@ use std::borrow::Cow; +use anyhow::{Context, Result}; +use rustc_hash::FxHashMap; + +use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::str::{leading_quote, trailing_quote}; use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; use ruff_python_literal::format::{ FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate, }; -use ruff_text_size::TextRange; -use rustc_hash::FxHashMap; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; -use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::str::{is_implicit_concatenation, leading_quote, trailing_quote}; +use ruff_python_parser::{lexer, Mode, Tok}; use ruff_source_file::Locator; +use ruff_text_size::TextRange; use crate::checkers::ast::Checker; use crate::line_width::LineLength; @@ -40,14 +42,16 @@ use crate::rules::pyupgrade::helpers::curly_escape; #[violation] pub struct FString; -impl AlwaysAutofixableViolation for FString { +impl Violation for FString { + const AUTOFIX: AutofixKind = AutofixKind::Sometimes; + #[derive_message_formats] fn message(&self) -> String { format!("Use f-string instead of `format` call") } - fn autofix_title(&self) -> String { - "Convert to f-string".to_string() + fn autofix_title(&self) -> Option { + Some("Convert to f-string".to_string()) } } @@ -59,36 +63,38 @@ impl AlwaysAutofixableViolation for FString { struct FormatSummaryValues<'a> { args: Vec<&'a Expr>, kwargs: FxHashMap<&'a str, &'a Expr>, + auto_index: usize, } impl<'a> FormatSummaryValues<'a> { - fn try_from_expr(expr: &'a Expr, locator: &'a Locator) -> Option { + fn try_from_call(call: &'a ast::ExprCall, locator: &'a Locator) -> Option { let mut extracted_args: Vec<&Expr> = Vec::new(); let mut extracted_kwargs: FxHashMap<&str, &Expr> = FxHashMap::default(); - if let Expr::Call(ast::ExprCall { args, keywords, .. }) = expr { - for arg in args { - if contains_invalids(locator.slice(arg.range())) - || locator.contains_line_break(arg.range()) - { - return None; - } - extracted_args.push(arg); + + for arg in &call.arguments.args { + if matches!(arg, Expr::Starred(..)) + || contains_quotes(locator.slice(arg.range())) + || locator.contains_line_break(arg.range()) + { + return None; } - for keyword in keywords { - let Keyword { - arg, - value, - range: _, - } = keyword; - if let Some(key) = arg { - if contains_invalids(locator.slice(value.range())) - || locator.contains_line_break(value.range()) - { - return None; - } - extracted_kwargs.insert(key, value); - } + extracted_args.push(arg); + } + for keyword in &call.arguments.keywords { + let Keyword { + arg, + value, + range: _, + } = keyword; + let Some(key) = arg else { + return None; + }; + if contains_quotes(locator.slice(value.range())) + || locator.contains_line_break(value.range()) + { + return None; } + extracted_kwargs.insert(key, value); } if extracted_args.is_empty() && extracted_kwargs.is_empty() { @@ -98,37 +104,31 @@ impl<'a> FormatSummaryValues<'a> { Some(Self { args: extracted_args, kwargs: extracted_kwargs, + auto_index: 0, }) } - fn consume_next(&mut self) -> Option<&Expr> { - if self.args.is_empty() { - None - } else { - Some(self.args.remove(0)) - } + /// Return the next positional argument. + fn arg_auto(&mut self) -> Option<&Expr> { + let idx = self.auto_index; + self.auto_index += 1; + self.arg_positional(idx) } - fn consume_arg(&mut self, index: usize) -> Option<&Expr> { - if self.args.len() > index { - Some(self.args.remove(index)) - } else { - None - } + /// Return the positional argument at the given index. + fn arg_positional(&self, index: usize) -> Option<&Expr> { + self.args.get(index).copied() } - fn consume_kwarg(&mut self, key: &str) -> Option<&Expr> { - self.kwargs.remove(key) + /// Return the keyword argument with the given name. + fn arg_keyword(&self, key: &str) -> Option<&Expr> { + self.kwargs.get(key).copied() } } -/// Return `true` if the string contains characters that are forbidden by -/// argument identifiers. -fn contains_invalids(string: &str) -> bool { - string.contains('*') - || string.contains('\'') - || string.contains('"') - || string.contains("await") +/// Return `true` if the string contains quotes. +fn contains_quotes(string: &str) -> bool { + string.contains(['\'', '"']) } enum FormatContext { @@ -184,59 +184,42 @@ fn formatted_expr<'a>(expr: &Expr, context: FormatContext, locator: &Locator<'a> } } -/// Generate an f-string from an [`Expr`]. -fn try_convert_to_f_string(expr: &Expr, locator: &Locator) -> Option { - let Expr::Call(ast::ExprCall { func, .. }) = expr else { - return None; - }; - let Expr::Attribute(ast::ExprAttribute { value, .. }) = func.as_ref() else { - return None; - }; - if !matches!( - value.as_ref(), - Expr::Constant(ast::ExprConstant { - value: Constant::Str(..), - .. - }), - ) { - return None; - }; - - let Some(mut summary) = FormatSummaryValues::try_from_expr(expr, locator) else { - return None; - }; - - let contents = locator.slice(value.range()); - - // Skip implicit string concatenations. - if is_implicit_concatenation(contents) { - return None; - } - +/// Convert a string `.format` call to an f-string. +/// +/// Returns `None` if the string does not require conversion, and `Err` if the conversion +/// is not possible. +fn try_convert_to_f_string( + range: TextRange, + summary: &mut FormatSummaryValues, + locator: &Locator, +) -> Result> { // Strip the unicode prefix. It's redundant in Python 3, and invalid when used // with f-strings. + let contents = locator.slice(range); let contents = if contents.starts_with('U') || contents.starts_with('u') { &contents[1..] } else { contents }; - if contents.is_empty() { - return None; - } // Remove the leading and trailing quotes. - let Some(leading_quote) = leading_quote(contents) else { - return None; - }; - let Some(trailing_quote) = trailing_quote(contents) else { - return None; - }; + let leading_quote = leading_quote(contents).context("Unable to identify leading quote")?; + let trailing_quote = trailing_quote(contents).context("Unable to identify trailing quote")?; let contents = &contents[leading_quote.len()..contents.len() - trailing_quote.len()]; + if contents.is_empty() { + return Ok(None); + } // Parse the format string. - let Ok(format_string) = FormatString::from_str(contents) else { - return None; - }; + let format_string = FormatString::from_str(contents)?; + + if format_string + .format_parts + .iter() + .all(|part| matches!(part, FormatPart::Literal(..))) + { + return Ok(None); + } let mut converted = String::with_capacity(contents.len()); for part in format_string.format_parts { @@ -248,12 +231,13 @@ fn try_convert_to_f_string(expr: &Expr, locator: &Locator) -> Option { } => { converted.push('{'); - let field = FieldName::parse(&field_name).ok()?; + let field = FieldName::parse(&field_name)?; let arg = match field.field_type { - FieldType::Auto => summary.consume_next(), - FieldType::Index(index) => summary.consume_arg(index), - FieldType::Keyword(name) => summary.consume_kwarg(&name), - }?; + FieldType::Auto => summary.arg_auto(), + FieldType::Index(index) => summary.arg_positional(index), + FieldType::Keyword(name) => summary.arg_keyword(&name), + } + .context("Unable to parse field")?; converted.push_str(&formatted_expr( arg, if field.parts.is_empty() { @@ -314,14 +298,14 @@ fn try_convert_to_f_string(expr: &Expr, locator: &Locator) -> Option { contents.push_str(leading_quote); contents.push_str(&converted); contents.push_str(trailing_quote); - Some(contents) + Ok(Some(contents)) } /// UP032 pub(crate) fn f_strings( checker: &mut Checker, + call: &ast::ExprCall, summary: &FormatSummary, - expr: &Expr, template: &Expr, line_length: LineLength, ) { @@ -329,16 +313,77 @@ pub(crate) fn f_strings( return; } - // Avoid refactoring strings that are implicitly concatenated. - if is_implicit_concatenation(checker.locator().slice(template.range())) { + let Expr::Attribute(ast::ExprAttribute { value, .. }) = call.func.as_ref() else { return; - } + }; - // Currently, the only issue we know of is in LibCST: - // https://github.com/Instagram/LibCST/issues/846 - let Some(mut contents) = try_convert_to_f_string(expr, checker.locator()) else { + if !matches!( + value.as_ref(), + Expr::Constant(ast::ExprConstant { + value: Constant::Str(..), + .. + }), + ) { + return; + }; + + let Some(mut summary) = FormatSummaryValues::try_from_call(call, checker.locator()) else { return; }; + let mut patches: Vec<(TextRange, String)> = vec![]; + let mut lex = lexer::lex_starts_at( + checker.locator().slice(call.func.range()), + Mode::Expression, + call.start(), + ) + .flatten(); + let end = loop { + match lex.next() { + Some((Tok::Dot, range)) => { + // ``` + // ( + // "a" + // " {} " + // "b" + // ).format(x) + // ``` + // ^ Get the position of the character before the dot. + // + // We know that the expression is a string literal, so we can safely assume that the + // dot is the start of an attribute access. + break range.start(); + } + Some((Tok::String { .. }, range)) => { + match try_convert_to_f_string(range, &mut summary, checker.locator()) { + Ok(Some(fstring)) => patches.push((range, fstring)), + // Skip any strings that don't require conversion (e.g., literal segments of an + // implicit concatenation). + Ok(None) => continue, + // If any of the segments fail to convert, then we can't convert the entire + // expression. + Err(_) => return, + } + } + Some(_) => continue, + None => unreachable!("Should break from the `Tok::Dot` arm"), + } + }; + if patches.is_empty() { + return; + } + + let mut contents = String::with_capacity(checker.locator().slice(call.range()).len()); + let mut prev_end = call.start(); + for (range, fstring) in patches { + contents.push_str( + checker + .locator() + .slice(TextRange::new(prev_end, range.start())), + ); + contents.push_str(&fstring); + prev_end = range.end(); + } + contents.push_str(checker.locator().slice(TextRange::new(prev_end, end))); // Avoid refactors that exceed the line length limit. let col_offset = template.start() - checker.locator().line_start(template.start()); @@ -358,20 +403,32 @@ pub(crate) fn f_strings( // If necessary, add a space between any leading keyword (`return`, `yield`, `assert`, etc.) // and the string. For example, `return"foo"` is valid, but `returnf"foo"` is not. - let existing = checker.locator().slice(TextRange::up_to(expr.start())); + let existing = checker.locator().slice(TextRange::up_to(call.start())); if existing .chars() .last() - .map_or(false, |char| char.is_ascii_alphabetic()) + .is_some_and(|char| char.is_ascii_alphabetic()) { contents.insert(0, ' '); } - let mut diagnostic = Diagnostic::new(FString, expr.range()); - if checker.patch(diagnostic.kind.rule()) { + let mut diagnostic = Diagnostic::new(FString, call.range()); + + // Avoid autofix if there are comments within the call: + // ``` + // "{}".format( + // 0, # 0 + // ) + // ``` + if checker.patch(diagnostic.kind.rule()) + && !checker + .indexer() + .comment_ranges() + .intersects(call.arguments.range()) + { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( contents, - expr.range(), + call.range(), ))); }; checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 1469cb7e74d95..00e5acb4af7c5 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -2,16 +2,18 @@ use anyhow::{anyhow, Result}; use libcst_native::{Arg, Expression}; use once_cell::sync::Lazy; use regex::Regex; -use ruff_python_ast::{Expr, Ranged}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_python_codegen::Stylist; use ruff_source_file::Locator; use crate::autofix::codemods::CodegenStylist; use crate::checkers::ast::Checker; -use crate::cst::matchers::{match_attribute, match_call_mut, match_expression}; +use crate::cst::matchers::{ + match_attribute, match_call_mut, match_expression, transform_expression_text, +}; use crate::registry::AsRule; use crate::rules::pyflakes::format::FormatSummary; @@ -55,13 +57,82 @@ impl Violation for FormatLiterals { } } +/// UP030 +pub(crate) fn format_literals( + checker: &mut Checker, + call: &ast::ExprCall, + summary: &FormatSummary, +) { + // The format we expect is, e.g.: `"{0} {1}".format(...)` + if summary.has_nested_parts { + return; + } + if !summary.keywords.is_empty() { + return; + } + if !summary.autos.is_empty() { + return; + } + if summary.indices.is_empty() { + return; + } + if (0..summary.indices.len()).any(|index| !summary.indices.contains(&index)) { + return; + } + + // If the positional indices aren't sequential (e.g., `"{1} {0}".format(1, 2)`), then we + // need to reorder the function arguments; so we need to ensure that the function + // arguments aren't splatted (e.g., `"{1} {0}".format(*foo)`), that there are a sufficient + // number of them, etc. + let arguments = if is_sequential(&summary.indices) { + Arguments::Preserve + } else { + // Ex) `"{1} {0}".format(foo=1, bar=2)` + if !call.arguments.keywords.is_empty() { + return; + } + + // Ex) `"{1} {0}".format(foo)` + if call.arguments.args.len() < summary.indices.len() { + return; + } + + // Ex) `"{1} {0}".format(*foo)` + if call + .arguments + .args + .iter() + .take(summary.indices.len()) + .any(Expr::is_starred_expr) + { + return; + } + + Arguments::Reorder(&summary.indices) + }; + + let mut diagnostic = Diagnostic::new(FormatLiterals, call.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.try_set_fix(|| { + generate_call(call, arguments, checker.locator(), checker.stylist()) + .map(|suggestion| Fix::suggested(Edit::range_replacement(suggestion, call.range()))) + }); + } + checker.diagnostics.push(diagnostic); +} + +/// Returns true if the indices are sequential. +fn is_sequential(indices: &[usize]) -> bool { + indices.iter().enumerate().all(|(idx, value)| idx == *value) +} + // An opening curly brace, followed by any integer, followed by any text, // followed by a closing brace. static FORMAT_SPECIFIER: Lazy = Lazy::new(|| Regex::new(r"\{(?P\d+)(?P.*?)}").unwrap()); /// Remove the explicit positional indices from a format string. -fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a mut typed_arena::Arena) { +fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a typed_arena::Arena) { match value { Expression::SimpleString(expr) => { expr.value = arena.alloc( @@ -94,7 +165,7 @@ fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a mut typed_arena: } /// Return the corrected argument vector. -fn generate_arguments<'a>(arguments: &[Arg<'a>], order: &'a [usize]) -> Result>> { +fn generate_arguments<'a>(arguments: &[Arg<'a>], order: &[usize]) -> Result>> { let mut new_arguments: Vec = Vec::with_capacity(arguments.len()); for (idx, given) in order.iter().enumerate() { // We need to keep the formatting in the same order but move the values. @@ -118,73 +189,45 @@ fn generate_arguments<'a>(arguments: &[Arg<'a>], order: &'a [usize]) -> Result bool { - indices.iter().enumerate().all(|(idx, value)| idx == *value) +#[derive(Debug, Copy, Clone)] +enum Arguments<'a> { + /// Preserve the arguments to the `.format(...)` call. + Preserve, + /// Reorder the arguments to the `.format(...)` call, based on the given + /// indices. + Reorder(&'a [usize]), } /// Returns the corrected function call. fn generate_call( - expr: &Expr, - correct_order: &[usize], + call: &ast::ExprCall, + arguments: Arguments, locator: &Locator, stylist: &Stylist, ) -> Result { - let content = locator.slice(expr.range()); - let parenthesized_content = format!("({content})"); - let mut expression = match_expression(&parenthesized_content)?; - - // Fix the call arguments. - let call = match_call_mut(&mut expression)?; - if !is_sequential(correct_order) { - call.args = generate_arguments(&call.args, correct_order)?; - } + let source_code = locator.slice(call.range()); + + let output = transform_expression_text(source_code, |source_code| { + let mut expression = match_expression(&source_code)?; + + // Fix the call arguments. + let call = match_call_mut(&mut expression)?; + if let Arguments::Reorder(order) = arguments { + call.args = generate_arguments(&call.args, order)?; + } - // Fix the string itself. - let item = match_attribute(&mut call.func)?; - let mut arena = typed_arena::Arena::new(); - remove_specifiers(&mut item.value, &mut arena); + // Fix the string itself. + let item = match_attribute(&mut call.func)?; + let arena = typed_arena::Arena::new(); + remove_specifiers(&mut item.value, &arena); - // Remove the parentheses (first and last characters). - let mut output = expression.codegen_stylist(stylist); - output.remove(0); - output.pop(); + Ok(expression.codegen_stylist(stylist)) + })?; // Ex) `'{' '0}'.format(1)` - if output == content { + if output == source_code { return Err(anyhow!("Unable to identify format literals")); } Ok(output) } - -/// UP030 -pub(crate) fn format_literals(checker: &mut Checker, summary: &FormatSummary, expr: &Expr) { - // The format we expect is, e.g.: `"{0} {1}".format(...)` - if summary.has_nested_parts { - return; - } - if !summary.keywords.is_empty() { - return; - } - if !summary.autos.is_empty() { - return; - } - if summary.indices.is_empty() { - return; - } - if (0..summary.indices.len()).any(|index| !summary.indices.contains(&index)) { - return; - } - - let mut diagnostic = Diagnostic::new(FormatLiterals, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - Ok(Fix::suggested(Edit::range_replacement( - generate_call(expr, &summary.indices, checker.locator(), checker.stylist())?, - expr.range(), - ))) - }); - } - checker.diagnostics.push(diagnostic); -} diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs index b70653f6dd148..1f50c974474d2 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{self as ast, Decorator, Expr, Keyword, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, Keyword, Ranged}; use ruff_text_size::TextRange; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; @@ -61,8 +61,12 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: for decorator in decorator_list { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, range: _, }) = &decorator.expression else { @@ -75,16 +79,14 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: && checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["functools", "lru_cache"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["functools", "lru_cache"])) { let Keyword { arg, value, range: _, } = &keywords[0]; - if arg.as_ref().map_or(false, |arg| arg == "maxsize") && is_const_none(value) { + if arg.as_ref().is_some_and(|arg| arg == "maxsize") && is_const_none(value) { let mut diagnostic = Diagnostic::new( LRUCacheWithMaxsizeNone, TextRange::new(func.end(), decorator.end()), diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs index 7d2364beaf361..09ba48c0ba27d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs @@ -1,8 +1,7 @@ -use ruff_python_ast::{self as ast, Decorator, Expr, Ranged}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Decorator, Expr, Ranged}; +use ruff_text_size::TextRange; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -59,8 +58,7 @@ pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list for decorator in decorator_list { let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments, range: _, }) = &decorator.expression else { @@ -68,24 +66,19 @@ pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list }; // Look for, e.g., `import functools; @functools.lru_cache()`. - if args.is_empty() - && keywords.is_empty() + if arguments.args.is_empty() + && arguments.keywords.is_empty() && checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["functools", "lru_cache"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["functools", "lru_cache"])) { let mut diagnostic = Diagnostic::new( LRUCacheWithoutParameters, TextRange::new(func.end(), decorator.end()), ); if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - checker.generator().expr(func), - decorator.expression.range(), - ))); + diagnostic.set_fix(Fix::automatic(Edit::range_deletion(arguments.range()))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/mod.rs b/crates/ruff/src/rules/pyupgrade/rules/mod.rs index 16ca52a57b49b..0a924c145120d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/mod.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/mod.rs @@ -32,6 +32,7 @@ pub(crate) use unpacked_list_comprehension::*; pub(crate) use use_pep585_annotation::*; pub(crate) use use_pep604_annotation::*; pub(crate) use use_pep604_isinstance::*; +pub(crate) use use_pep695_type_alias::*; pub(crate) use useless_metaclass_type::*; pub(crate) use useless_object_inheritance::*; pub(crate) use yield_in_for_loop::*; @@ -70,6 +71,7 @@ mod unpacked_list_comprehension; mod use_pep585_annotation; mod use_pep604_annotation; mod use_pep604_isinstance; +mod use_pep695_type_alias; mod useless_metaclass_type; mod useless_object_inheritance; mod yield_in_for_loop; diff --git a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs index f0942da106bf0..a106efcaa9a87 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs @@ -2,11 +2,10 @@ use std::fmt; use std::str::FromStr; use num_bigint::BigInt; -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::str::is_implicit_concatenation; +use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -38,8 +37,14 @@ impl FromStr for LiteralType { impl From for Constant { fn from(value: LiteralType) -> Self { match value { - LiteralType::Str => Constant::Str(String::new()), - LiteralType::Bytes => Constant::Bytes(vec![]), + LiteralType::Str => Constant::Str(ast::StringConstant { + value: String::new(), + implicit_concatenated: false, + }), + LiteralType::Bytes => Constant::Bytes(ast::BytesConstant { + value: Vec::new(), + implicit_concatenated: false, + }), LiteralType::Int => Constant::Int(BigInt::from(0)), LiteralType::Float => Constant::Float(0.0), LiteralType::Bool => Constant::Bool(false), @@ -124,12 +129,21 @@ impl AlwaysAutofixableViolation for NativeLiterals { /// UP018 pub(crate) fn native_literals( checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], + call: &ast::ExprCall, + parent_expr: Option<&ast::Expr>, ) { - let Expr::Name(ast::ExprName { id, .. }) = func else { + let ast::ExprCall { + func, + arguments: + ast::Arguments { + args, + keywords, + range: _, + }, + range: _, + } = call; + + let Expr::Name(ast::ExprName { ref id, .. }) = func.as_ref() else { return; }; @@ -149,8 +163,8 @@ pub(crate) fn native_literals( if checker.semantic().in_f_string() { if checker .semantic() - .expr_ancestors() - .filter(|expr| expr.is_joined_str_expr()) + .current_expressions() + .filter(|expr| expr.is_f_string_expr()) .count() > 1 { @@ -160,13 +174,20 @@ pub(crate) fn native_literals( match args.get(0) { None => { - let mut diagnostic = Diagnostic::new(NativeLiterals { literal_type }, expr.range()); + let mut diagnostic = Diagnostic::new(NativeLiterals { literal_type }, call.range()); + + // Do not suggest fix for attribute access on an int like `int().attribute` + // Ex) `int().denominator` is valid but `0.denominator` is not + if literal_type == LiteralType::Int && matches!(parent_expr, Some(Expr::Attribute(_))) { + return; + } + if checker.patch(diagnostic.kind.rule()) { let constant = Constant::from(literal_type); let content = checker.generator().constant(&constant); diagnostic.set_fix(Fix::automatic(Edit::range_replacement( content, - expr.range(), + call.range(), ))); } checker.diagnostics.push(diagnostic); @@ -176,6 +197,11 @@ pub(crate) fn native_literals( return; }; + // Skip implicit string concatenations. + if value.is_implicit_concatenated() { + return; + } + let Ok(arg_literal_type) = LiteralType::try_from(value) else { return; }; @@ -186,18 +212,20 @@ pub(crate) fn native_literals( let arg_code = checker.locator().slice(arg.range()); - // Skip implicit string concatenations. - if matches!(arg_literal_type, LiteralType::Str | LiteralType::Bytes) - && is_implicit_concatenation(arg_code) - { - return; - } + // Attribute access on an integer requires the integer to be parenthesized to disambiguate from a float + // Ex) `(7).denominator` is valid but `7.denominator` is not + // Note that floats do not have this problem + // Ex) `(1.0).real` is valid and `1.0.real` is too + let content = match (parent_expr, value) { + (Some(Expr::Attribute(_)), Constant::Int(_)) => format!("({arg_code})"), + _ => arg_code.to_string(), + }; - let mut diagnostic = Diagnostic::new(NativeLiterals { literal_type }, expr.range()); + let mut diagnostic = Diagnostic::new(NativeLiterals { literal_type }, call.range()); if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - arg_code.to_string(), - expr.range(), + content, + call.range(), ))); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs index 91177031014d9..85fe77c588c6d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs @@ -50,9 +50,7 @@ pub(crate) fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) { if checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["io", "open"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["io", "open"])) { let mut diagnostic = Diagnostic::new(OpenAlias, expr.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs index 4fdd9c994134a..9ec667999d5b9 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs @@ -36,7 +36,7 @@ use crate::registry::AsRule; /// - [Python documentation: `OSError`](https://docs.python.org/3/library/exceptions.html#OSError) #[violation] pub struct OSErrorAlias { - pub name: Option, + name: Option, } impl AlwaysAutofixableViolation for OSErrorAlias { @@ -56,7 +56,7 @@ impl AlwaysAutofixableViolation for OSErrorAlias { /// Return `true` if an [`Expr`] is an alias of `OSError`. fn is_alias(expr: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { matches!( call_path.as_slice(), ["", "EnvironmentError" | "IOError" | "WindowsError"] @@ -67,9 +67,9 @@ fn is_alias(expr: &Expr, semantic: &SemanticModel) -> bool { /// Return `true` if an [`Expr`] is `OSError`. fn is_os_error(expr: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(expr).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "OSError"]) - }) + semantic + .resolve_call_path(expr) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "OSError"])) } /// Create a [`Diagnostic`] for a single target, like an [`Expr::Name`]. diff --git a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs index 47fd10d09503b..d8c5fdcb8203f 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs @@ -124,8 +124,8 @@ fn fix_py2_block(checker: &Checker, stmt_if: &StmtIf, branch: &IfElifBranch) -> BranchKind::If => match stmt_if.elif_else_clauses.first() { // If we have a lone `if`, delete as statement (insert pass in parent if required) None => { - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); Some(Fix::suggested(edit)) } @@ -201,10 +201,10 @@ fn fix_py2_block(checker: &Checker, stmt_if: &StmtIf, branch: &IfElifBranch) -> .elif_else_clauses .iter() .map(Ranged::start) - .find(|start| *start > branch.range.start()); + .find(|start| *start > branch.start()); Some(Fix::suggested(Edit::deletion( - branch.range.start(), - next_start.unwrap_or(branch.range.end()), + branch.start(), + next_start.unwrap_or(branch.end()), ))) } } @@ -256,7 +256,7 @@ fn fix_py3_block(checker: &mut Checker, stmt_if: &StmtIf, branch: &IfElifBranch) .slice(TextRange::new(branch.test.end(), end.end())); Some(Fix::suggested(Edit::range_replacement( format!("else{text}"), - TextRange::new(branch.range.start(), stmt_if.end()), + TextRange::new(branch.start(), stmt_if.end()), ))) } } @@ -282,9 +282,7 @@ pub(crate) fn outdated_version_block(checker: &mut Checker, stmt_if: &StmtIf) { if !checker .semantic() .resolve_call_path(left) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["sys", "version_info"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["sys", "version_info"])) { continue; } diff --git a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs index 3b84a63208634..68032f5b9ff7f 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs @@ -4,10 +4,10 @@ use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; use ruff_python_literal::cformat::{ CConversionFlags, CFormatPart, CFormatPrecision, CFormatQuantity, CFormatString, }; -use ruff_python_parser::{lexer, Mode, Tok}; +use ruff_python_parser::{lexer, AsMode, Tok}; use ruff_text_size::TextRange; -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; +use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::str::{leading_quote, trailing_quote}; use ruff_python_ast::whitespace::indentation; @@ -43,14 +43,16 @@ use crate::rules::pyupgrade::helpers::curly_escape; #[violation] pub struct PrintfStringFormatting; -impl AlwaysAutofixableViolation for PrintfStringFormatting { +impl Violation for PrintfStringFormatting { + const AUTOFIX: AutofixKind = AutofixKind::Sometimes; + #[derive_message_formats] fn message(&self) -> String { format!("Use format specifiers instead of percent format") } - fn autofix_title(&self) -> String { - "Replace with format specifiers".to_string() + fn autofix_title(&self) -> Option { + Some("Replace with format specifiers".to_string()) } } @@ -200,7 +202,10 @@ fn clean_params_dictionary( match key { Some(key) => { if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(key_string), + value: + Constant::Str(ast::StringConstant { + value: key_string, .. + }), .. }) = key { @@ -295,7 +300,7 @@ fn convertible(format_string: &CFormatString, params: &Expr) -> bool { } // No equivalent in format. - if fmt.mapping_key.as_ref().map_or(false, String::is_empty) { + if fmt.mapping_key.as_ref().is_some_and(String::is_empty) { return false; } @@ -339,7 +344,7 @@ pub(crate) fn printf_string_formatting( let mut extension = None; for (tok, range) in lexer::lex_starts_at( checker.locator().slice(expr.range()), - Mode::Module, + checker.source_type.as_mode(), expr.start(), ) .flatten() @@ -398,7 +403,7 @@ pub(crate) fn printf_string_formatting( // Parse the parameters. let params_string = match right { - Expr::Constant(_) | Expr::JoinedStr(_) => { + Expr::Constant(_) | Expr::FString(_) => { format!("({})", checker.locator().slice(right.range())) } Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) => { @@ -467,7 +472,15 @@ pub(crate) fn printf_string_formatting( contents.push_str(&format!(".format{params_string}")); let mut diagnostic = Diagnostic::new(PrintfStringFormatting, expr.range()); - if checker.patch(diagnostic.kind.rule()) { + // Avoid autofix if there are comments within the right-hand side: + // ``` + // "%s" % ( + // 0, # 0 + // ) + // ``` + if checker.patch(diagnostic.kind.rule()) + && !checker.indexer().comment_ranges().intersects(right.range()) + { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( contents, expr.range(), diff --git a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs index df0a1156b5bb6..0a99e7a3f72a8 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -1,15 +1,14 @@ use std::str::FromStr; use anyhow::{anyhow, Result}; -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; -use ruff_python_parser::{lexer, Mode}; -use ruff_text_size::TextSize; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Constant, Expr, PySourceType, Ranged}; +use ruff_python_parser::{lexer, AsMode}; use ruff_python_semantic::SemanticModel; use ruff_source_file::Locator; +use ruff_text_size::TextSize; use crate::checkers::ast::Checker; use crate::registry::Rule; @@ -64,26 +63,32 @@ impl AlwaysAutofixableViolation for RedundantOpenModes { } /// UP015 -pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { - let Some((mode_param, keywords)) = match_open(expr, checker.semantic()) else { +pub(crate) fn redundant_open_modes(checker: &mut Checker, call: &ast::ExprCall) { + if !is_open_builtin(call.func.as_ref(), checker.semantic()) { return; - }; - match mode_param { + } + + match call.arguments.find_argument("mode", 1) { None => { - if !keywords.is_empty() { - if let Some(keyword) = find_keyword(keywords, MODE_KEYWORD_ARGUMENT) { + if !call.arguments.is_empty() { + if let Some(keyword) = call.arguments.find_keyword(MODE_KEYWORD_ARGUMENT) { if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(mode_param_value), + value: + Constant::Str(ast::StringConstant { + value: mode_param_value, + .. + }), .. }) = &keyword.value { - if let Ok(mode) = OpenMode::from_str(mode_param_value.as_str()) { + if let Ok(mode) = OpenMode::from_str(mode_param_value) { checker.diagnostics.push(create_check( - expr, + call, &keyword.value, mode.replacement_value(), checker.locator(), checker.patch(Rule::RedundantOpenModes), + checker.source_type, )); } } @@ -96,13 +101,14 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { .. }) = &mode_param { - if let Ok(mode) = OpenMode::from_str(value.as_str()) { + if let Ok(mode) = OpenMode::from_str(value) { checker.diagnostics.push(create_check( - expr, + call, mode_param, mode.replacement_value(), checker.locator(), checker.patch(Rule::RedundantOpenModes), + checker.source_type, )); } } @@ -113,25 +119,12 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { const OPEN_FUNC_NAME: &str = "open"; const MODE_KEYWORD_ARGUMENT: &str = "mode"; -fn match_open<'a>( - expr: &'a Expr, - model: &SemanticModel, -) -> Option<(Option<&'a Expr>, &'a [Keyword])> { - let ast::ExprCall { - func, - args, - keywords, - range: _, - } = expr.as_call_expr()?; - - let ast::ExprName { id, .. } = func.as_name_expr()?; - - if id.as_str() == OPEN_FUNC_NAME && model.is_builtin(id) { - // Return the "open mode" parameter and keywords. - Some((args.get(1), keywords)) - } else { - None - } +/// Returns `true` if the given `call` is a call to the `open` builtin. +fn is_open_builtin(func: &Expr, semantic: &SemanticModel) -> bool { + let Some(ast::ExprName { id, .. }) = func.as_name_expr() else { + return false; + }; + id.as_str() == OPEN_FUNC_NAME && semantic.is_builtin(id) } #[derive(Debug, Copy, Clone)] @@ -176,12 +169,13 @@ impl OpenMode { } } -fn create_check( - expr: &Expr, +fn create_check( + expr: &T, mode_param: &Expr, replacement_value: Option<&str>, locator: &Locator, patch: bool, + source_type: PySourceType, ) -> Diagnostic { let mut diagnostic = Diagnostic::new( RedundantOpenModes { @@ -197,14 +191,19 @@ fn create_check( ))); } else { diagnostic.try_set_fix(|| { - create_remove_param_fix(locator, expr, mode_param).map(Fix::automatic) + create_remove_param_fix(locator, expr, mode_param, source_type).map(Fix::automatic) }); } } diagnostic } -fn create_remove_param_fix(locator: &Locator, expr: &Expr, mode_param: &Expr) -> Result { +fn create_remove_param_fix( + locator: &Locator, + expr: &T, + mode_param: &Expr, + source_type: PySourceType, +) -> Result { let content = locator.slice(expr.range()); // Find the last comma before mode_param and create a deletion fix // starting from the comma and ending after mode_param. @@ -212,7 +211,8 @@ fn create_remove_param_fix(locator: &Locator, expr: &Expr, mode_param: &Expr) -> let mut fix_end: Option = None; let mut is_first_arg: bool = false; let mut delete_first_arg: bool = false; - for (tok, range) in lexer::lex_starts_at(content, Mode::Module, expr.start()).flatten() { + for (tok, range) in lexer::lex_starts_at(content, source_type.as_mode(), expr.start()).flatten() + { if range.start() == mode_param.start() { if is_first_arg { delete_first_arg = true; diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs index 80b2891cf8342..df120210f4c3e 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs @@ -1,12 +1,10 @@ use anyhow::Result; -use ruff_python_ast::{Expr, Keyword, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; -use ruff_source_file::Locator; +use ruff_python_ast::{self as ast, Keyword, Ranged}; -use crate::autofix::edits::remove_argument; +use crate::autofix::edits::{remove_argument, Parentheses}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -53,12 +51,10 @@ impl AlwaysAutofixableViolation for ReplaceStdoutStderr { /// Generate a [`Edit`] for a `stdout` and `stderr` [`Keyword`] pair. fn generate_fix( - locator: &Locator, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], stdout: &Keyword, stderr: &Keyword, + call: &ast::ExprCall, + source: &str, ) -> Result { let (first, second) = if stdout.start() < stderr.start() { (stdout, stderr) @@ -68,36 +64,26 @@ fn generate_fix( Ok(Fix::suggested_edits( Edit::range_replacement("capture_output=True".to_string(), first.range()), [remove_argument( - locator, - func.end(), - second.range(), - args, - keywords, - false, + second, + &call.arguments, + Parentheses::Preserve, + source, )?], )) } /// UP022 -pub(crate) fn replace_stdout_stderr( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], - keywords: &[Keyword], -) { +pub(crate) fn replace_stdout_stderr(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["subprocess", "run"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "run"])) { // Find `stdout` and `stderr` kwargs. - let Some(stdout) = find_keyword(keywords, "stdout") else { + let Some(stdout) = call.arguments.find_keyword("stdout") else { return; }; - let Some(stderr) = find_keyword(keywords, "stderr") else { + let Some(stderr) = call.arguments.find_keyword("stderr") else { return; }; @@ -105,24 +91,19 @@ pub(crate) fn replace_stdout_stderr( if !checker .semantic() .resolve_call_path(&stdout.value) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["subprocess", "PIPE"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "PIPE"])) || !checker .semantic() .resolve_call_path(&stderr.value) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["subprocess", "PIPE"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "PIPE"])) { return; } - let mut diagnostic = Diagnostic::new(ReplaceStdoutStderr, expr.range()); + let mut diagnostic = Diagnostic::new(ReplaceStdoutStderr, call.range()); if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - generate_fix(checker.locator(), func, args, keywords, stdout, stderr) - }); + diagnostic + .try_set_fix(|| generate_fix(stdout, stderr, call, checker.locator().contents())); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs index ef9837d5dd513..b8938400a319f 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs @@ -1,9 +1,7 @@ -use ruff_python_ast::{Expr, Keyword, Ranged}; -use ruff_text_size::{TextLen, TextRange}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::helpers::find_keyword; +use ruff_python_ast::{self as ast, Ranged}; +use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -50,15 +48,13 @@ impl AlwaysAutofixableViolation for ReplaceUniversalNewlines { } /// UP021 -pub(crate) fn replace_universal_newlines(checker: &mut Checker, func: &Expr, kwargs: &[Keyword]) { +pub(crate) fn replace_universal_newlines(checker: &mut Checker, call: &ast::ExprCall) { if checker .semantic() - .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["subprocess", "run"]) - }) + .resolve_call_path(&call.func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["subprocess", "run"])) { - let Some(kwarg) = find_keyword(kwargs, "universal_newlines") else { + let Some(kwarg) = call.arguments.find_keyword("universal_newlines") else { return; }; let range = TextRange::at(kwarg.start(), "universal_newlines".text_len()); diff --git a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs index 46ec27b6167c3..8b247f26747ff 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs @@ -1,11 +1,10 @@ -use ruff_python_ast::{self as ast, Arg, ArgWithDefault, Expr, Ranged, Stmt}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Parameter, ParameterWithDefault, Ranged, Stmt}; +use ruff_text_size::TextSize; use crate::checkers::ast::Checker; use crate::registry::AsRule; -use crate::rules::pyupgrade::fixes; /// ## What it does /// Checks for `super` calls that pass redundant arguments. @@ -59,58 +58,45 @@ impl AlwaysAutofixableViolation for SuperCallWithParameters { } } -/// Returns `true` if a call is an argumented `super` invocation. -fn is_super_call_with_arguments(func: &Expr, args: &[Expr]) -> bool { - if let Expr::Name(ast::ExprName { id, .. }) = func { - id == "super" && !args.is_empty() - } else { - false - } -} - /// UP008 -pub(crate) fn super_call_with_parameters( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], -) { +pub(crate) fn super_call_with_parameters(checker: &mut Checker, call: &ast::ExprCall) { // Only bother going through the super check at all if we're in a `super` call. // (We check this in `super_args` too, so this is just an optimization.) - if !is_super_call_with_arguments(func, args) { + if !is_super_call_with_arguments(call) { return; } - let scope = checker.semantic().scope(); + let scope = checker.semantic().current_scope(); // Check: are we in a Function scope? - if !scope.kind.is_any_function() { + if !scope.kind.is_function() { return; } - let mut parents = checker.semantic().parents(); + let mut parents = checker.semantic().current_statements(); // For a `super` invocation to be unnecessary, the first argument needs to match // the enclosing class, and the second argument needs to match the first // argument to the enclosing function. - let [first_arg, second_arg] = args else { + let [first_arg, second_arg] = call.arguments.args.as_slice() else { return; }; // Find the enclosing function definition (if any). let Some(Stmt::FunctionDef(ast::StmtFunctionDef { - args: parent_args, .. + parameters: parent_parameters, + .. })) = parents.find(|stmt| stmt.is_function_def_stmt()) else { return; }; // Extract the name of the first argument to the enclosing function. - let Some(ArgWithDefault { - def: Arg { - arg: parent_arg, .. + let Some(ParameterWithDefault { + parameter: Parameter { + name: parent_arg, .. }, .. - }) = parent_args.args.first() + }) = parent_parameters.args.first() else { return; }; @@ -141,13 +127,21 @@ pub(crate) fn super_call_with_parameters( drop(parents); - let mut diagnostic = Diagnostic::new(SuperCallWithParameters, expr.range()); + let mut diagnostic = Diagnostic::new(SuperCallWithParameters, call.arguments.range()); if checker.patch(diagnostic.kind.rule()) { - if let Some(edit) = - fixes::remove_super_arguments(checker.locator(), checker.stylist(), expr) - { - diagnostic.set_fix(Fix::suggested(edit)); - } + diagnostic.set_fix(Fix::suggested(Edit::deletion( + call.arguments.start() + TextSize::new(1), + call.arguments.end() - TextSize::new(1), + ))); } checker.diagnostics.push(diagnostic); } + +/// Returns `true` if a call is an argumented `super` invocation. +fn is_super_call_with_arguments(call: &ast::ExprCall) -> bool { + if let Expr::Name(ast::ExprName { id, .. }) = call.func.as_ref() { + id == "super" && !call.arguments.is_empty() + } else { + false + } +} diff --git a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs index 322e40032860e..c4baff5ef3357 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs @@ -54,19 +54,17 @@ impl Violation for TypeOfPrimitive { /// UP003 pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) { - if args.len() != 1 { + let [arg] = args else { return; - } + }; if !checker .semantic() .resolve_call_path(func) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "type"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "type"])) { return; } - let Expr::Constant(ast::ExprConstant { value, .. }) = &args[0] else { + let Expr::Constant(ast::ExprConstant { value, .. }) = &arg else { return; }; let Some(primitive) = Primitive::from_constant(value) else { diff --git a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs index fd82c568d1b8a..1abac409ad1d6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs @@ -49,9 +49,7 @@ pub(crate) fn typing_text_str_alias(checker: &mut Checker, expr: &Expr) { if checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["typing", "Text"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "Text"])) { let mut diagnostic = Diagnostic::new(TypingTextStrAlias, expr.range()); if checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs index 01e12717a8e6a..919a26bff6097 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs @@ -122,21 +122,22 @@ pub(crate) fn unnecessary_builtin_import( ); if checker.patch(diagnostic.kind.rule()) { diagnostic.try_set_fix(|| { - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); - let unused_imports: Vec = unused_imports - .iter() - .map(|alias| format!("{module}.{}", alias.name)) - .collect(); + let statement = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = autofix::edits::remove_unused_imports( - unused_imports.iter().map(String::as_str), - stmt, + unused_imports + .iter() + .map(|alias| &alias.name) + .map(ruff_python_ast::Identifier::as_str), + statement, parent, checker.locator(), checker.stylist(), checker.indexer(), )?; - Ok(Fix::suggested(edit).isolate(checker.isolation(parent))) + Ok(Fix::suggested(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs index 5d9817ca4a539..b45b3a5e3f5a3 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs @@ -1,10 +1,6 @@ -use std::ops::Add; - -use ruff_python_ast::{self as ast, Ranged}; -use ruff_text_size::{TextRange, TextSize}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -44,54 +40,20 @@ impl AlwaysAutofixableViolation for UnnecessaryClassParentheses { /// UP039 pub(crate) fn unnecessary_class_parentheses(checker: &mut Checker, class_def: &ast::StmtClassDef) { - if !class_def.bases.is_empty() || !class_def.keywords.is_empty() { - return; - } - - let offset = class_def.name.end(); - let contents = checker.locator().after(offset); - - // Find the open and closing parentheses between the class name and the colon, if they exist. - let mut depth = 0u32; - let mut start = None; - let mut end = None; - for (i, c) in contents.char_indices() { - match c { - '(' => { - if depth == 0 { - start = Some(i); - } - depth = depth.saturating_add(1); - } - ')' => { - depth = depth.saturating_sub(1); - if depth == 0 { - end = Some(i + c.len_utf8()); - } - } - ':' => { - if depth == 0 { - break; - } - } - _ => {} - } - } - let (Some(start), Some(end)) = (start, end) else { + let Some(arguments) = class_def.arguments.as_deref() else { return; }; - // Convert to `TextSize`. - let start = TextSize::try_from(start).unwrap(); - let end = TextSize::try_from(end).unwrap(); - - // Add initial offset. - let start = offset.add(start); - let end = offset.add(end); + if !arguments.args.is_empty() || !arguments.keywords.is_empty() { + return; + } - let mut diagnostic = Diagnostic::new(UnnecessaryClassParentheses, TextRange::new(start, end)); + let mut diagnostic = Diagnostic::new(UnnecessaryClassParentheses, arguments.range()); if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::deletion(start, end))); + diagnostic.set_fix(Fix::automatic(Edit::deletion( + arguments.start(), + arguments.end(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs index cd0cdf213e8e5..72e55a6b11ab6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs @@ -5,6 +5,7 @@ use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_index::Indexer; use ruff_source_file::Locator; +use ruff_text_size::TextRange; use crate::registry::AsRule; use crate::settings::Settings; @@ -55,20 +56,45 @@ pub(crate) fn unnecessary_coding_comment( ) { // The coding comment must be on one of the first two lines. Since each comment spans at least // one line, we only need to check the first two comments at most. - for range in indexer.comment_ranges().iter().take(2) { - let line = locator.slice(*range); - if CODING_COMMENT_REGEX.is_match(line) { + for comment_range in indexer.comment_ranges().iter().take(2) { + // If leading content is not whitespace then it's not a valid coding comment e.g. + // ``` + // print(x) # coding=utf8 + // ``` + let line_range = locator.full_line_range(comment_range.start()); + if !locator + .slice(TextRange::new(line_range.start(), comment_range.start())) + .trim() + .is_empty() + { + continue; + } + + // If the line is after a continuation then it's not a valid coding comment e.g. + // ``` + // x = 1 \ + // # coding=utf8 + // x = 2 + // ``` + if indexer + .preceded_by_continuations(line_range.start(), locator) + .is_some() + { + continue; + } + + if CODING_COMMENT_REGEX.is_match(locator.slice(line_range)) { #[allow(deprecated)] - let line = locator.compute_line_index(range.start()); - if line.to_zero_indexed() > 1 { + let index = locator.compute_line_index(line_range.start()); + if index.to_zero_indexed() > 1 { continue; } - let mut diagnostic = Diagnostic::new(UTF8EncodingDeclaration, *range); + let mut diagnostic = Diagnostic::new(UTF8EncodingDeclaration, *comment_range); if settings.rules.should_fix(diagnostic.kind.rule()) { diagnostic.set_fix(Fix::automatic(Edit::deletion( - range.start(), - locator.full_line_end(range.end()), + line_range.start(), + line_range.end(), ))); } diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs index 9dad88d987f45..0c48fdcc55570 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs @@ -1,12 +1,11 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Keyword, Ranged}; -use ruff_python_parser::{lexer, Mode, Tok}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Keyword, PySourceType, Ranged}; +use ruff_python_parser::{lexer, AsMode, Tok}; use ruff_source_file::Locator; +use ruff_text_size::TextRange; -use crate::autofix::edits::remove_argument; +use crate::autofix::edits::{remove_argument, Parentheses}; use crate::checkers::ast::Checker; use crate::registry::Rule; @@ -95,23 +94,21 @@ enum EncodingArg<'a> { /// Return the encoding argument to an `encode` call, if it can be determined to be a /// UTF-8-equivalent encoding. -fn match_encoding_arg<'a>(args: &'a [Expr], kwargs: &'a [Keyword]) -> Option> { - match (args.len(), kwargs.len()) { +fn match_encoding_arg(arguments: &Arguments) -> Option { + match (arguments.args.as_slice(), arguments.keywords.as_slice()) { // Ex `"".encode()` - (0, 0) => return Some(EncodingArg::Empty), + ([], []) => return Some(EncodingArg::Empty), // Ex `"".encode(encoding)` - (1, 0) => { - let arg = &args[0]; + ([arg], []) => { if is_utf8_encoding_arg(arg) { return Some(EncodingArg::Positional(arg)); } } // Ex `"".encode(kwarg=kwarg)` - (0, 1) => { - let kwarg = &kwargs[0]; - if kwarg.arg.as_ref().map_or(false, |arg| arg == "encoding") { - if is_utf8_encoding_arg(&kwarg.value) { - return Some(EncodingArg::Keyword(kwarg)); + ([], [keyword]) => { + if keyword.arg.as_ref().is_some_and(|arg| arg == "encoding") { + if is_utf8_encoding_arg(&keyword.value) { + return Some(EncodingArg::Keyword(keyword)); } } } @@ -122,12 +119,18 @@ fn match_encoding_arg<'a>(args: &'a [Expr], kwargs: &'a [Keyword]) -> Option Fix { +fn replace_with_bytes_literal( + locator: &Locator, + expr: &T, + source_type: PySourceType, +) -> Fix { // Build up a replacement string by prefixing all string tokens with `b`. let contents = locator.slice(expr.range()); let mut replacement = String::with_capacity(contents.len() + 1); let mut prev = expr.start(); - for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, expr.start()).flatten() { + for (tok, range) in + lexer::lex_starts_at(contents, source_type.as_mode(), expr.start()).flatten() + { match tok { Tok::Dot => break, Tok::String { .. } => { @@ -149,14 +152,8 @@ fn replace_with_bytes_literal(locator: &Locator, expr: &Expr) -> Fix { } /// UP012 -pub(crate) fn unnecessary_encode_utf8( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], - kwargs: &[Keyword], -) { - let Some(variable) = match_encoded_variable(func) else { +pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCall) { + let Some(variable) = match_encoded_variable(&call.func) else { return; }; match variable { @@ -165,17 +162,21 @@ pub(crate) fn unnecessary_encode_utf8( .. }) => { // Ex) `"str".encode()`, `"str".encode("utf-8")` - if let Some(encoding_arg) = match_encoding_arg(args, kwargs) { + if let Some(encoding_arg) = match_encoding_arg(&call.arguments) { if literal.is_ascii() { // Ex) Convert `"foo".encode()` to `b"foo"`. let mut diagnostic = Diagnostic::new( UnnecessaryEncodeUTF8 { reason: Reason::BytesLiteral, }, - expr.range(), + call.range(), ); if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.set_fix(replace_with_bytes_literal(checker.locator(), expr)); + diagnostic.set_fix(replace_with_bytes_literal( + checker.locator(), + call, + checker.source_type, + )); } checker.diagnostics.push(diagnostic); } else if let EncodingArg::Keyword(kwarg) = encoding_arg { @@ -185,17 +186,15 @@ pub(crate) fn unnecessary_encode_utf8( UnnecessaryEncodeUTF8 { reason: Reason::DefaultArgument, }, - expr.range(), + call.range(), ); if checker.patch(Rule::UnnecessaryEncodeUTF8) { diagnostic.try_set_fix(|| { remove_argument( - checker.locator(), - func.end(), - kwarg.range(), - args, - kwargs, - false, + kwarg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), ) .map(Fix::automatic) }); @@ -207,17 +206,15 @@ pub(crate) fn unnecessary_encode_utf8( UnnecessaryEncodeUTF8 { reason: Reason::DefaultArgument, }, - expr.range(), + call.range(), ); if checker.patch(Rule::UnnecessaryEncodeUTF8) { diagnostic.try_set_fix(|| { remove_argument( - checker.locator(), - func.end(), - arg.range(), - args, - kwargs, - false, + arg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), ) .map(Fix::automatic) }); @@ -227,8 +224,8 @@ pub(crate) fn unnecessary_encode_utf8( } } // Ex) `f"foo{bar}".encode("utf-8")` - Expr::JoinedStr(_) => { - if let Some(encoding_arg) = match_encoding_arg(args, kwargs) { + Expr::FString(_) => { + if let Some(encoding_arg) = match_encoding_arg(&call.arguments) { if let EncodingArg::Keyword(kwarg) = encoding_arg { // Ex) Convert `f"unicode text©".encode(encoding="utf-8")` to // `f"unicode text©".encode()`. @@ -236,17 +233,15 @@ pub(crate) fn unnecessary_encode_utf8( UnnecessaryEncodeUTF8 { reason: Reason::DefaultArgument, }, - expr.range(), + call.range(), ); if checker.patch(Rule::UnnecessaryEncodeUTF8) { diagnostic.try_set_fix(|| { remove_argument( - checker.locator(), - func.end(), - kwarg.range(), - args, - kwargs, - false, + kwarg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), ) .map(Fix::automatic) }); @@ -258,17 +253,15 @@ pub(crate) fn unnecessary_encode_utf8( UnnecessaryEncodeUTF8 { reason: Reason::DefaultArgument, }, - expr.range(), + call.range(), ); if checker.patch(Rule::UnnecessaryEncodeUTF8) { diagnostic.try_set_fix(|| { remove_argument( - checker.locator(), - func.end(), - arg.range(), - args, - kwargs, - false, + arg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), ) .map(Fix::automatic) }); diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs index 52c5b543c8c9f..402de0a9a3653 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs @@ -111,21 +111,22 @@ pub(crate) fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, name if checker.patch(diagnostic.kind.rule()) { diagnostic.try_set_fix(|| { - let unused_imports: Vec = unused_imports - .iter() - .map(|alias| format!("__future__.{}", alias.name)) - .collect(); - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); + let statement = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = autofix::edits::remove_unused_imports( - unused_imports.iter().map(String::as_str), - stmt, + unused_imports + .iter() + .map(|alias| &alias.name) + .map(ruff_python_ast::Identifier::as_str), + statement, parent, checker.locator(), checker.stylist(), checker.indexer(), )?; - Ok(Fix::suggested(edit).isolate(checker.isolation(parent))) + Ok(Fix::suggested(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs index b77a2d315de8a..30f04f90c84a3 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -20,8 +20,16 @@ use crate::registry::AsRule; /// /// When available, the [PEP 585] syntax should be used instead of importing /// members from the `typing` module, as it's more concise and readable. -/// Importing those members from `typing` is considered deprecated as of PEP -/// 585. +/// Importing those members from `typing` is considered deprecated as of [PEP +/// 585]. +/// +/// This rule is enabled when targeting Python 3.9 or later (see: +/// [`target-version`]). By default, it's _also_ enabled for earlier Python +/// versions if `from __future__ import annotations` is present, as +/// `__future__` annotations are not evaluated at runtime. If your code relies +/// on runtime type annotations (either directly or via a library like +/// Pydantic), you can disable this behavior for Python versions prior to 3.9 +/// by setting [`pyupgrade.keep-runtime-typing`] to `true`. /// /// ## Example /// ```python diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index c2c619b740942..4c480dd8649aa 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -18,6 +18,14 @@ use crate::registry::AsRule; /// `|` operator. This syntax is more concise and readable than the previous /// `typing.Union` and `typing.Optional` syntaxes. /// +/// This rule is enabled when targeting Python 3.10 or later (see: +/// [`target-version`]). By default, it's _also_ enabled for earlier Python +/// versions if `from __future__ import annotations` is present, as +/// `__future__` annotations are not evaluated at runtime. If your code relies +/// on runtime type annotations (either directly or via a library like +/// Pydantic), you can disable this behavior for Python versions prior to 3.10 +/// by setting [`pyupgrade.keep-runtime-typing`] to `true`. +/// /// ## Example /// ```python /// from typing import Union diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs new file mode 100644 index 0000000000000..4c51960ec9325 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep695_type_alias.rs @@ -0,0 +1,182 @@ +use ast::{Constant, ExprCall, ExprConstant}; +use ruff_python_ast::{ + self as ast, + visitor::{self, Visitor}, + Expr, ExprName, ExprSubscript, Identifier, Ranged, Stmt, StmtAnnAssign, StmtAssign, + StmtTypeAlias, TypeParam, TypeParamTypeVar, +}; +use ruff_python_semantic::SemanticModel; + +use crate::{registry::AsRule, settings::types::PythonVersion}; +use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_text_size::TextRange; + +use crate::checkers::ast::Checker; + +/// ## What it does +/// Checks for use of `TypeAlias` annotation for declaring type aliases. +/// +/// ## Why is this bad? +/// The `type` keyword was introduced in Python 3.12 by PEP-695 for defining type aliases. +/// The type keyword is easier to read and provides cleaner support for generics. +/// +/// ## Example +/// ```python +/// ListOfInt: TypeAlias = list[int] +/// ``` +/// +/// Use instead: +/// ```python +/// type ListOfInt = list[int] +/// ``` +#[violation] +pub struct NonPEP695TypeAlias { + name: String, +} + +impl Violation for NonPEP695TypeAlias { + const AUTOFIX: AutofixKind = AutofixKind::Always; + + #[derive_message_formats] + fn message(&self) -> String { + let NonPEP695TypeAlias { name } = self; + format!("Type alias `{name}` uses `TypeAlias` annotation instead of the `type` keyword") + } + + fn autofix_title(&self) -> Option { + Some("Use the `type` keyword".to_string()) + } +} + +/// UP040 +pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign) { + let StmtAnnAssign { + target, + annotation, + value, + .. + } = stmt; + + // Syntax only available in 3.12+ + if checker.settings.target_version < PythonVersion::Py312 { + return; + } + + if !checker + .semantic() + .match_typing_expr(annotation, "TypeAlias") + { + return; + } + + let Expr::Name(ExprName { id: name, .. }) = target.as_ref() else { + return; + }; + + let Some(value) = value else { + return; + }; + + // TODO(zanie): We should check for generic type variables used in the value and define them + // as type params instead + let mut diagnostic = Diagnostic::new(NonPEP695TypeAlias { name: name.clone() }, stmt.range()); + if checker.patch(diagnostic.kind.rule()) { + let mut visitor = TypeVarReferenceVisitor { + names: vec![], + semantic: checker.semantic(), + }; + visitor.visit_expr(value); + + let type_params = if visitor.names.is_empty() { + None + } else { + Some(ast::TypeParams { + range: TextRange::default(), + type_params: visitor + .names + .iter() + .map(|name| { + TypeParam::TypeVar(TypeParamTypeVar { + range: TextRange::default(), + name: Identifier::new(name.id.clone(), TextRange::default()), + bound: None, + }) + }) + .collect(), + }) + }; + + diagnostic.set_fix(Fix::automatic(Edit::range_replacement( + checker.generator().stmt(&Stmt::from(StmtTypeAlias { + range: TextRange::default(), + name: target.clone(), + type_params, + value: value.clone(), + })), + stmt.range(), + ))); + } + checker.diagnostics.push(diagnostic); +} + +struct TypeVarReferenceVisitor<'a> { + names: Vec<&'a ExprName>, + semantic: &'a SemanticModel<'a>, +} + +/// Recursively collects the names of type variable references present in an expression. +impl<'a> Visitor<'a> for TypeVarReferenceVisitor<'a> { + fn visit_expr(&mut self, expr: &'a Expr) { + match expr { + Expr::Name(name) if name.ctx.is_load() => { + let Some(Stmt::Assign(StmtAssign { value, .. })) = self + .semantic + .lookup_symbol(name.id.as_str()) + .and_then(|binding_id| { + self.semantic + .binding(binding_id) + .source + .map(|node_id| self.semantic.statement(node_id)) + }) + else { + return; + }; + + match value.as_ref() { + Expr::Subscript(ExprSubscript { + value: ref subscript_value, + .. + }) => { + if self.semantic.match_typing_expr(subscript_value, "TypeVar") { + self.names.push(name); + } + } + Expr::Call(ExprCall { + func, arguments, .. + }) => { + // TODO(zanieb): Add support for bounds and variance declarations + // for now this only supports `TypeVar("...")` + if self.semantic.match_typing_expr(func, "TypeVar") + && arguments.args.len() == 1 + && arguments.args.first().is_some_and(|arg| { + matches!( + arg, + Expr::Constant(ExprConstant { + value: Constant::Str(_), + .. + }) + ) + }) + && arguments.keywords.is_empty() + { + self.names.push(name); + } + } + _ => {} + } + } + _ => visitor::walk_expr(self, expr), + } + } +} diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs index 70fd1418574ec..df5795f5d967e 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs @@ -63,10 +63,12 @@ pub(crate) fn useless_metaclass_type( let mut diagnostic = Diagnostic::new(UselessMetaclassType, stmt.range()); if checker.patch(diagnostic.kind.rule()) { - let stmt = checker.semantic().stmt(); - let parent = checker.semantic().stmt_parent(); + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); let edit = autofix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::automatic(edit).isolate(checker.isolation(parent))); + diagnostic.set_fix(Fix::automatic(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs index 32db85e693fdb..2e2de98529305 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs @@ -1,9 +1,8 @@ -use ruff_python_ast::{self as ast, Expr, Ranged}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Ranged}; -use crate::autofix::edits::remove_argument; +use crate::autofix::edits::{remove_argument, Parentheses}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -47,8 +46,12 @@ impl AlwaysAutofixableViolation for UselessObjectInheritance { /// UP004 pub(crate) fn useless_object_inheritance(checker: &mut Checker, class_def: &ast::StmtClassDef) { - for expr in &class_def.bases { - let Expr::Name(ast::ExprName { id, .. }) = expr else { + let Some(arguments) = class_def.arguments.as_deref() else { + return; + }; + + for base in &arguments.args { + let Expr::Name(ast::ExprName { id, .. }) = base else { continue; }; if id != "object" { @@ -62,19 +65,17 @@ pub(crate) fn useless_object_inheritance(checker: &mut Checker, class_def: &ast: UselessObjectInheritance { name: class_def.name.to_string(), }, - expr.range(), + base.range(), ); if checker.patch(diagnostic.kind.rule()) { diagnostic.try_set_fix(|| { - let edit = remove_argument( - checker.locator(), - class_def.name.end(), - expr.range(), - &class_def.bases, - &class_def.keywords, - true, - )?; - Ok(Fix::automatic(edit)) + remove_argument( + base, + arguments, + Parentheses::Remove, + checker.locator().contents(), + ) + .map(Fix::automatic) }); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs index ddb832a4a5c69..0662a0c0404fa 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs @@ -1,12 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, ExprContext, Ranged, Stmt}; -use rustc_hash::FxHashMap; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::statement_visitor::StatementVisitor; -use ruff_python_ast::types::RefEquality; -use ruff_python_ast::visitor::Visitor; -use ruff_python_ast::{statement_visitor, visitor}; +use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -46,155 +40,103 @@ impl AlwaysAutofixableViolation for YieldInForLoop { } } -/// Return `true` if the two expressions are equivalent, and consistent solely -/// of tuples and names. -fn is_same_expr(a: &Expr, b: &Expr) -> bool { - match (&a, &b) { - (Expr::Name(ast::ExprName { id: a, .. }), Expr::Name(ast::ExprName { id: b, .. })) => { - a == b - } - ( - Expr::Tuple(ast::ExprTuple { elts: a, .. }), - Expr::Tuple(ast::ExprTuple { elts: b, .. }), - ) => a.len() == b.len() && a.iter().zip(b).all(|(a, b)| is_same_expr(a, b)), - _ => false, +/// UP028 +pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt_for: &ast::StmtFor) { + // Intentionally omit async contexts. + if checker.semantic().in_async_context() { + return; } -} -/// Collect all named variables in an expression consisting solely of tuples and -/// names. -fn collect_names(expr: &Expr) -> Vec<&str> { - match expr { - Expr::Name(ast::ExprName { id, .. }) => vec![id], - Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().flat_map(collect_names).collect(), - _ => panic!("Expected: Expr::Name | Expr::Tuple"), + let ast::StmtFor { + target, + iter, + body, + orelse, + is_async: _, + range: _, + } = stmt_for; + + // If there is an else statement, don't rewrite. + if !orelse.is_empty() { + return; } -} - -#[derive(Debug)] -struct YieldFrom<'a> { - stmt: &'a Stmt, - body: &'a Stmt, - iter: &'a Expr, - names: Vec<&'a str>, -} -#[derive(Default)] -struct YieldFromVisitor<'a> { - yields: Vec>, -} - -impl<'a> StatementVisitor<'a> for YieldFromVisitor<'a> { - fn visit_stmt(&mut self, stmt: &'a Stmt) { - match stmt { - Stmt::For(ast::StmtFor { - target, - body, - orelse, - iter, - .. - }) => { - // If there is an else statement, don't rewrite. - if !orelse.is_empty() { - return; - } - // If there's any logic besides a yield, don't rewrite. - let [body] = body.as_slice() else { - return; - }; - // If the body is not a yield, don't rewrite. - if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body { - if let Expr::Yield(ast::ExprYield { - value: Some(value), - range: _, - }) = value.as_ref() - { - if is_same_expr(target, value) { - self.yields.push(YieldFrom { - stmt, - body, - iter, - names: collect_names(target), - }); - } - } - } - } - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { - // Don't recurse into anything that defines a new scope. - } - _ => statement_visitor::walk_stmt(self, stmt), - } + // If there's any logic besides a yield, don't rewrite. + let [body] = body.as_slice() else { + return; + }; + + // If the body is not a yield, don't rewrite. + let Stmt::Expr(ast::StmtExpr { value, range: _ }) = &body else { + return; + }; + let Expr::Yield(ast::ExprYield { + value: Some(value), + range: _, + }) = value.as_ref() + else { + return; + }; + + // If the target is not the same as the value, don't rewrite. For example, we should rewrite + // `for x in y: yield x` to `yield from y`, but not `for x in y: yield x + 1`. + if !is_same_expr(target, value) { + return; } -} - -#[derive(Default)] -struct ReferenceVisitor<'a> { - parent: Option<&'a Stmt>, - references: FxHashMap, Vec<&'a str>>, -} -impl<'a> Visitor<'a> for ReferenceVisitor<'a> { - fn visit_stmt(&mut self, stmt: &'a Stmt) { - let prev_parent = self.parent; - self.parent = Some(stmt); - visitor::walk_stmt(self, stmt); - self.parent = prev_parent; + // If any of the bound names are used outside of the yield itself, don't rewrite. + if collect_names(value).any(|name| { + checker + .semantic() + .current_scope() + .get_all(name.id.as_str()) + .any(|binding_id| { + let binding = checker.semantic().binding(binding_id); + binding.references.iter().any(|reference_id| { + checker.semantic().reference(*reference_id).range() != name.range() + }) + }) + }) { + return; } - fn visit_expr(&mut self, expr: &'a Expr) { - match expr { - Expr::Name(ast::ExprName { id, ctx, range: _ }) => { - if matches!(ctx, ExprContext::Load | ExprContext::Del) { - if let Some(parent) = self.parent { - self.references - .entry(RefEquality(parent)) - .or_default() - .push(id); - } - } - } - _ => visitor::walk_expr(self, expr), - } + let mut diagnostic = Diagnostic::new(YieldInForLoop, stmt_for.range()); + if checker.patch(diagnostic.kind.rule()) { + let contents = checker.locator().slice(iter.range()); + let contents = format!("yield from {contents}"); + diagnostic.set_fix(Fix::suggested(Edit::range_replacement( + contents, + stmt_for.range(), + ))); } + checker.diagnostics.push(diagnostic); } -/// UP028 -pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt: &Stmt) { - // Intentionally omit async functions. - if let Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) = stmt { - let yields = { - let mut visitor = YieldFromVisitor::default(); - visitor.visit_body(body); - visitor.yields - }; - - let references = { - let mut visitor = ReferenceVisitor::default(); - visitor.visit_body(body); - visitor.references - }; - - for item in yields { - // If any of the bound names are used outside of the loop, don't rewrite. - if references.iter().any(|(stmt, names)| { - stmt != &RefEquality(item.stmt) - && stmt != &RefEquality(item.body) - && item.names.iter().any(|name| names.contains(name)) - }) { - continue; - } - - let mut diagnostic = Diagnostic::new(YieldInForLoop, item.stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let contents = checker.locator().slice(item.iter.range()); - let contents = format!("yield from {contents}"); - diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - contents, - item.stmt.range(), - ))); - } - checker.diagnostics.push(diagnostic); +/// Return `true` if the two expressions are equivalent, and both consistent solely +/// of tuples and names. +fn is_same_expr(left: &Expr, right: &Expr) -> bool { + match (&left, &right) { + (Expr::Name(left), Expr::Name(right)) => left.id == right.id, + (Expr::Tuple(left), Expr::Tuple(right)) => { + left.elts.len() == right.elts.len() + && left + .elts + .iter() + .zip(right.elts.iter()) + .all(|(left, right)| is_same_expr(left, right)) } + _ => false, } } + +/// Collect all named variables in an expression consisting solely of tuples and +/// names. +fn collect_names<'a>(expr: &'a Expr) -> Box + 'a> { + Box::new( + expr.as_name_expr().into_iter().chain( + expr.as_tuple_expr() + .into_iter() + .flat_map(|tuple| tuple.elts.iter().flat_map(collect_names)), + ), + ) +} diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap index 40458ff41e892..afafaf4db3469 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap @@ -1,11 +1,11 @@ --- source: crates/ruff/src/rules/pyupgrade/mod.rs --- -UP008.py:17:18: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:17:23: UP008 [*] Use `super()` instead of `super(__class__, self)` | 16 | def wrong(self): 17 | parent = super(Child, self) # wrong - | ^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^ UP008 18 | super(Child, self).method # wrong 19 | super( | @@ -21,12 +21,12 @@ UP008.py:17:18: UP008 [*] Use `super()` instead of `super(__class__, self)` 19 19 | super( 20 20 | Child, -UP008.py:18:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:18:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 16 | def wrong(self): 17 | parent = super(Child, self) # wrong 18 | super(Child, self).method # wrong - | ^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^ UP008 19 | super( 20 | Child, | @@ -42,12 +42,12 @@ UP008.py:18:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 20 20 | Child, 21 21 | self, -UP008.py:19:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:19:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 17 | parent = super(Child, self) # wrong 18 | super(Child, self).method # wrong 19 | super( - | _________^ + | ______________^ 20 | | Child, 21 | | self, 22 | | ).method() # wrong @@ -68,12 +68,12 @@ UP008.py:19:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 24 21 | 25 22 | class BaseClass: -UP008.py:36:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:36:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 34 | class MyClass(BaseClass): 35 | def normal(self): 36 | super(MyClass, self).f() # can use super() - | ^^^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^^^ UP008 37 | super().f() | = help: Remove `super` parameters @@ -88,11 +88,11 @@ UP008.py:36:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 38 38 | 39 39 | def different_argument(self, other): -UP008.py:50:13: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:50:18: UP008 [*] Use `super()` instead of `super(__class__, self)` | 49 | def inner_argument(self): 50 | super(MyClass, self).f() # can use super() - | ^^^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^^^ UP008 51 | super().f() | = help: Remove `super` parameters diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_10.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_10.py.snap new file mode 100644 index 0000000000000..870ad3bf5d625 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_10.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_6.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_6.py.snap new file mode 100644 index 0000000000000..faf65dd7cc43a --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_6.py.snap @@ -0,0 +1,18 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- +UP009_6.py:1:2: UP009 [*] UTF-8 encoding declaration is unnecessary + | +1 | # coding=utf8 + | ^^^^^^^^^^^^^ UP009 +2 | print("Hello world") + | + = help: Remove unnecessary coding comment + +ℹ Fix +1 |- # coding=utf8 +2 1 | print("Hello world") +3 2 | +4 3 | """ + + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_7.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_7.py.snap new file mode 100644 index 0000000000000..8e7962330df15 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_7.py.snap @@ -0,0 +1,18 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- +UP009_7.py:1:2: UP009 [*] UTF-8 encoding declaration is unnecessary + | +1 | # coding=utf8 + | ^^^^^^^^^^^^^ UP009 +2 | print("Hello world") + | + = help: Remove unnecessary coding comment + +ℹ Fix +1 |- # coding=utf8 +2 1 | print("Hello world") +3 2 | +4 3 | """ + + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_8.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_8.py.snap new file mode 100644 index 0000000000000..870ad3bf5d625 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_8.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_9.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_9.py.snap new file mode 100644 index 0000000000000..870ad3bf5d625 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP009_9.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP018.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP018.py.snap index e88d44ee729a0..ee269a7004b88 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP018.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP018.py.snap @@ -1,294 +1,317 @@ --- source: crates/ruff/src/rules/pyupgrade/mod.rs --- -UP018.py:36:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) +UP018.py:37:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) | -35 | # These become string or byte literals -36 | str() +36 | # These become string or byte literals +37 | str() | ^^^^^ UP018 -37 | str("foo") -38 | str(""" +38 | str("foo") +39 | str(""" | = help: Replace with empty string ℹ Fix -33 33 | bool(1.0) -34 34 | -35 35 | # These become string or byte literals -36 |-str() - 36 |+"" -37 37 | str("foo") -38 38 | str(""" -39 39 | foo""") +34 34 | int().denominator +35 35 | +36 36 | # These become string or byte literals +37 |-str() + 37 |+"" +38 38 | str("foo") +39 39 | str(""" +40 40 | foo""") -UP018.py:37:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) +UP018.py:38:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) | -35 | # These become string or byte literals -36 | str() -37 | str("foo") +36 | # These become string or byte literals +37 | str() +38 | str("foo") | ^^^^^^^^^^ UP018 -38 | str(""" -39 | foo""") +39 | str(""" +40 | foo""") | = help: Replace with empty string ℹ Fix -34 34 | -35 35 | # These become string or byte literals -36 36 | str() -37 |-str("foo") - 37 |+"foo" -38 38 | str(""" -39 39 | foo""") -40 40 | bytes() +35 35 | +36 36 | # These become string or byte literals +37 37 | str() +38 |-str("foo") + 38 |+"foo" +39 39 | str(""" +40 40 | foo""") +41 41 | bytes() -UP018.py:38:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) +UP018.py:39:1: UP018 [*] Unnecessary `str` call (rewrite as a literal) | -36 | str() -37 | str("foo") -38 | / str(""" -39 | | foo""") +37 | str() +38 | str("foo") +39 | / str(""" +40 | | foo""") | |_______^ UP018 -40 | bytes() -41 | bytes(b"foo") +41 | bytes() +42 | bytes(b"foo") | = help: Replace with empty string ℹ Fix -35 35 | # These become string or byte literals -36 36 | str() -37 37 | str("foo") -38 |-str(""" -39 |-foo""") - 38 |+""" - 39 |+foo""" -40 40 | bytes() -41 41 | bytes(b"foo") -42 42 | bytes(b""" +36 36 | # These become string or byte literals +37 37 | str() +38 38 | str("foo") +39 |-str(""" +40 |-foo""") + 39 |+""" + 40 |+foo""" +41 41 | bytes() +42 42 | bytes(b"foo") +43 43 | bytes(b""" -UP018.py:40:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) +UP018.py:41:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) | -38 | str(""" -39 | foo""") -40 | bytes() +39 | str(""" +40 | foo""") +41 | bytes() | ^^^^^^^ UP018 -41 | bytes(b"foo") -42 | bytes(b""" +42 | bytes(b"foo") +43 | bytes(b""" | = help: Replace with empty bytes ℹ Fix -37 37 | str("foo") -38 38 | str(""" -39 39 | foo""") -40 |-bytes() - 40 |+b"" -41 41 | bytes(b"foo") -42 42 | bytes(b""" -43 43 | foo""") +38 38 | str("foo") +39 39 | str(""" +40 40 | foo""") +41 |-bytes() + 41 |+b"" +42 42 | bytes(b"foo") +43 43 | bytes(b""" +44 44 | foo""") -UP018.py:41:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) +UP018.py:42:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) | -39 | foo""") -40 | bytes() -41 | bytes(b"foo") +40 | foo""") +41 | bytes() +42 | bytes(b"foo") | ^^^^^^^^^^^^^ UP018 -42 | bytes(b""" -43 | foo""") +43 | bytes(b""" +44 | foo""") | = help: Replace with empty bytes ℹ Fix -38 38 | str(""" -39 39 | foo""") -40 40 | bytes() -41 |-bytes(b"foo") - 41 |+b"foo" -42 42 | bytes(b""" -43 43 | foo""") -44 44 | f"{str()}" +39 39 | str(""" +40 40 | foo""") +41 41 | bytes() +42 |-bytes(b"foo") + 42 |+b"foo" +43 43 | bytes(b""" +44 44 | foo""") +45 45 | f"{str()}" -UP018.py:42:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) +UP018.py:43:1: UP018 [*] Unnecessary `bytes` call (rewrite as a literal) | -40 | bytes() -41 | bytes(b"foo") -42 | / bytes(b""" -43 | | foo""") +41 | bytes() +42 | bytes(b"foo") +43 | / bytes(b""" +44 | | foo""") | |_______^ UP018 -44 | f"{str()}" -45 | int() +45 | f"{str()}" +46 | int() | = help: Replace with empty bytes ℹ Fix -39 39 | foo""") -40 40 | bytes() -41 41 | bytes(b"foo") -42 |-bytes(b""" -43 |-foo""") - 42 |+b""" - 43 |+foo""" -44 44 | f"{str()}" -45 45 | int() -46 46 | int(1) +40 40 | foo""") +41 41 | bytes() +42 42 | bytes(b"foo") +43 |-bytes(b""" +44 |-foo""") + 43 |+b""" + 44 |+foo""" +45 45 | f"{str()}" +46 46 | int() +47 47 | int(1) -UP018.py:44:4: UP018 [*] Unnecessary `str` call (rewrite as a literal) +UP018.py:45:4: UP018 [*] Unnecessary `str` call (rewrite as a literal) | -42 | bytes(b""" -43 | foo""") -44 | f"{str()}" +43 | bytes(b""" +44 | foo""") +45 | f"{str()}" | ^^^^^ UP018 -45 | int() -46 | int(1) +46 | int() +47 | int(1) | = help: Replace with empty string ℹ Fix -41 41 | bytes(b"foo") -42 42 | bytes(b""" -43 43 | foo""") -44 |-f"{str()}" - 44 |+f"{''}" -45 45 | int() -46 46 | int(1) -47 47 | float() +42 42 | bytes(b"foo") +43 43 | bytes(b""" +44 44 | foo""") +45 |-f"{str()}" + 45 |+f"{''}" +46 46 | int() +47 47 | int(1) +48 48 | float() -UP018.py:45:1: UP018 [*] Unnecessary `int` call (rewrite as a literal) +UP018.py:46:1: UP018 [*] Unnecessary `int` call (rewrite as a literal) | -43 | foo""") -44 | f"{str()}" -45 | int() +44 | foo""") +45 | f"{str()}" +46 | int() | ^^^^^ UP018 -46 | int(1) -47 | float() +47 | int(1) +48 | float() | = help: Replace with 0 ℹ Fix -42 42 | bytes(b""" -43 43 | foo""") -44 44 | f"{str()}" -45 |-int() - 45 |+0 -46 46 | int(1) -47 47 | float() -48 48 | float(1.0) +43 43 | bytes(b""" +44 44 | foo""") +45 45 | f"{str()}" +46 |-int() + 46 |+0 +47 47 | int(1) +48 48 | float() +49 49 | float(1.0) -UP018.py:46:1: UP018 [*] Unnecessary `int` call (rewrite as a literal) +UP018.py:47:1: UP018 [*] Unnecessary `int` call (rewrite as a literal) | -44 | f"{str()}" -45 | int() -46 | int(1) +45 | f"{str()}" +46 | int() +47 | int(1) | ^^^^^^ UP018 -47 | float() -48 | float(1.0) +48 | float() +49 | float(1.0) | = help: Replace with 0 ℹ Fix -43 43 | foo""") -44 44 | f"{str()}" -45 45 | int() -46 |-int(1) - 46 |+1 -47 47 | float() -48 48 | float(1.0) -49 49 | bool() +44 44 | foo""") +45 45 | f"{str()}" +46 46 | int() +47 |-int(1) + 47 |+1 +48 48 | float() +49 49 | float(1.0) +50 50 | bool() -UP018.py:47:1: UP018 [*] Unnecessary `float` call (rewrite as a literal) +UP018.py:48:1: UP018 [*] Unnecessary `float` call (rewrite as a literal) | -45 | int() -46 | int(1) -47 | float() +46 | int() +47 | int(1) +48 | float() | ^^^^^^^ UP018 -48 | float(1.0) -49 | bool() +49 | float(1.0) +50 | bool() | = help: Replace with 0.0 ℹ Fix -44 44 | f"{str()}" -45 45 | int() -46 46 | int(1) -47 |-float() - 47 |+0.0 -48 48 | float(1.0) -49 49 | bool() -50 50 | bool(True) +45 45 | f"{str()}" +46 46 | int() +47 47 | int(1) +48 |-float() + 48 |+0.0 +49 49 | float(1.0) +50 50 | bool() +51 51 | bool(True) -UP018.py:48:1: UP018 [*] Unnecessary `float` call (rewrite as a literal) +UP018.py:49:1: UP018 [*] Unnecessary `float` call (rewrite as a literal) | -46 | int(1) -47 | float() -48 | float(1.0) +47 | int(1) +48 | float() +49 | float(1.0) | ^^^^^^^^^^ UP018 -49 | bool() -50 | bool(True) +50 | bool() +51 | bool(True) | = help: Replace with 0.0 ℹ Fix -45 45 | int() -46 46 | int(1) -47 47 | float() -48 |-float(1.0) - 48 |+1.0 -49 49 | bool() -50 50 | bool(True) -51 51 | bool(False) +46 46 | int() +47 47 | int(1) +48 48 | float() +49 |-float(1.0) + 49 |+1.0 +50 50 | bool() +51 51 | bool(True) +52 52 | bool(False) -UP018.py:49:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) +UP018.py:50:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) | -47 | float() -48 | float(1.0) -49 | bool() +48 | float() +49 | float(1.0) +50 | bool() | ^^^^^^ UP018 -50 | bool(True) -51 | bool(False) +51 | bool(True) +52 | bool(False) | = help: Replace with `False` ℹ Fix -46 46 | int(1) -47 47 | float() -48 48 | float(1.0) -49 |-bool() - 49 |+False -50 50 | bool(True) -51 51 | bool(False) +47 47 | int(1) +48 48 | float() +49 49 | float(1.0) +50 |-bool() + 50 |+False +51 51 | bool(True) +52 52 | bool(False) +53 53 | -UP018.py:50:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) +UP018.py:51:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) | -48 | float(1.0) -49 | bool() -50 | bool(True) +49 | float(1.0) +50 | bool() +51 | bool(True) | ^^^^^^^^^^ UP018 -51 | bool(False) +52 | bool(False) | = help: Replace with `False` ℹ Fix -47 47 | float() -48 48 | float(1.0) -49 49 | bool() -50 |-bool(True) - 50 |+True -51 51 | bool(False) +48 48 | float() +49 49 | float(1.0) +50 50 | bool() +51 |-bool(True) + 51 |+True +52 52 | bool(False) +53 53 | +54 54 | # These become a literal but retain parentheses -UP018.py:51:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) +UP018.py:52:1: UP018 [*] Unnecessary `bool` call (rewrite as a literal) | -49 | bool() -50 | bool(True) -51 | bool(False) +50 | bool() +51 | bool(True) +52 | bool(False) | ^^^^^^^^^^^ UP018 +53 | +54 | # These become a literal but retain parentheses | = help: Replace with `False` ℹ Fix -48 48 | float(1.0) -49 49 | bool() -50 50 | bool(True) -51 |-bool(False) - 51 |+False +49 49 | float(1.0) +50 50 | bool() +51 51 | bool(True) +52 |-bool(False) + 52 |+False +53 53 | +54 54 | # These become a literal but retain parentheses +55 55 | int(1).denominator + +UP018.py:55:1: UP018 [*] Unnecessary `int` call (rewrite as a literal) + | +54 | # These become a literal but retain parentheses +55 | int(1).denominator + | ^^^^^^ UP018 + | + = help: Replace with 0 + +ℹ Fix +52 52 | bool(False) +53 53 | +54 54 | # These become a literal but retain parentheses +55 |-int(1).denominator + 55 |+(1).denominator diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_0.py.snap index 393bdb502c78c..a0b8e1a467227 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_0.py.snap @@ -249,7 +249,255 @@ UP030_0.py:34:1: UP030 Use implicit references for positional format fields 33 | 34 | '{' '0}'.format(1) | ^^^^^^^^^^^^^^^^^^ UP030 +35 | +36 | args = list(range(10)) | = help: Remove explicit positional indices +UP030_0.py:39:1: UP030 [*] Use implicit references for positional format fields + | +37 | kwargs = {x: x for x in range(10)} +38 | +39 | "{0}".format(*args) + | ^^^^^^^^^^^^^^^^^^^ UP030 +40 | +41 | "{0}".format(**kwargs) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +36 36 | args = list(range(10)) +37 37 | kwargs = {x: x for x in range(10)} +38 38 | +39 |-"{0}".format(*args) + 39 |+"{}".format(*args) +40 40 | +41 41 | "{0}".format(**kwargs) +42 42 | + +UP030_0.py:41:1: UP030 [*] Use implicit references for positional format fields + | +39 | "{0}".format(*args) +40 | +41 | "{0}".format(**kwargs) + | ^^^^^^^^^^^^^^^^^^^^^^ UP030 +42 | +43 | "{0}_{1}".format(*args) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +38 38 | +39 39 | "{0}".format(*args) +40 40 | +41 |-"{0}".format(**kwargs) + 41 |+"{}".format(**kwargs) +42 42 | +43 43 | "{0}_{1}".format(*args) +44 44 | + +UP030_0.py:43:1: UP030 [*] Use implicit references for positional format fields + | +41 | "{0}".format(**kwargs) +42 | +43 | "{0}_{1}".format(*args) + | ^^^^^^^^^^^^^^^^^^^^^^^ UP030 +44 | +45 | "{0}_{1}".format(1, *args) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +40 40 | +41 41 | "{0}".format(**kwargs) +42 42 | +43 |-"{0}_{1}".format(*args) + 43 |+"{}_{}".format(*args) +44 44 | +45 45 | "{0}_{1}".format(1, *args) +46 46 | + +UP030_0.py:45:1: UP030 [*] Use implicit references for positional format fields + | +43 | "{0}_{1}".format(*args) +44 | +45 | "{0}_{1}".format(1, *args) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +46 | +47 | "{0}_{1}".format(1, 2, *args) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +42 42 | +43 43 | "{0}_{1}".format(*args) +44 44 | +45 |-"{0}_{1}".format(1, *args) + 45 |+"{}_{}".format(1, *args) +46 46 | +47 47 | "{0}_{1}".format(1, 2, *args) +48 48 | + +UP030_0.py:47:1: UP030 [*] Use implicit references for positional format fields + | +45 | "{0}_{1}".format(1, *args) +46 | +47 | "{0}_{1}".format(1, 2, *args) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +48 | +49 | "{0}_{1}".format(*args, 1, 2) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +44 44 | +45 45 | "{0}_{1}".format(1, *args) +46 46 | +47 |-"{0}_{1}".format(1, 2, *args) + 47 |+"{}_{}".format(1, 2, *args) +48 48 | +49 49 | "{0}_{1}".format(*args, 1, 2) +50 50 | + +UP030_0.py:49:1: UP030 [*] Use implicit references for positional format fields + | +47 | "{0}_{1}".format(1, 2, *args) +48 | +49 | "{0}_{1}".format(*args, 1, 2) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +50 | +51 | "{0}_{1}_{2}".format(1, **kwargs) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +46 46 | +47 47 | "{0}_{1}".format(1, 2, *args) +48 48 | +49 |-"{0}_{1}".format(*args, 1, 2) + 49 |+"{}_{}".format(*args, 1, 2) +50 50 | +51 51 | "{0}_{1}_{2}".format(1, **kwargs) +52 52 | + +UP030_0.py:51:1: UP030 [*] Use implicit references for positional format fields + | +49 | "{0}_{1}".format(*args, 1, 2) +50 | +51 | "{0}_{1}_{2}".format(1, **kwargs) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +52 | +53 | "{0}_{1}_{2}".format(1, 2, **kwargs) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +48 48 | +49 49 | "{0}_{1}".format(*args, 1, 2) +50 50 | +51 |-"{0}_{1}_{2}".format(1, **kwargs) + 51 |+"{}_{}_{}".format(1, **kwargs) +52 52 | +53 53 | "{0}_{1}_{2}".format(1, 2, **kwargs) +54 54 | + +UP030_0.py:53:1: UP030 [*] Use implicit references for positional format fields + | +51 | "{0}_{1}_{2}".format(1, **kwargs) +52 | +53 | "{0}_{1}_{2}".format(1, 2, **kwargs) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +54 | +55 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +50 50 | +51 51 | "{0}_{1}_{2}".format(1, **kwargs) +52 52 | +53 |-"{0}_{1}_{2}".format(1, 2, **kwargs) + 53 |+"{}_{}_{}".format(1, 2, **kwargs) +54 54 | +55 55 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) +56 56 | + +UP030_0.py:55:1: UP030 [*] Use implicit references for positional format fields + | +53 | "{0}_{1}_{2}".format(1, 2, **kwargs) +54 | +55 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +56 | +57 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +52 52 | +53 53 | "{0}_{1}_{2}".format(1, 2, **kwargs) +54 54 | +55 |-"{0}_{1}_{2}".format(1, 2, 3, **kwargs) + 55 |+"{}_{}_{}".format(1, 2, 3, **kwargs) +56 56 | +57 57 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) +58 58 | + +UP030_0.py:57:1: UP030 [*] Use implicit references for positional format fields + | +55 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) +56 | +57 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +58 | +59 | "{1}_{0}".format(1, 2, *args) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +54 54 | +55 55 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) +56 56 | +57 |-"{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) + 57 |+"{}_{}_{}".format(1, 2, 3, *args, **kwargs) +58 58 | +59 59 | "{1}_{0}".format(1, 2, *args) +60 60 | + +UP030_0.py:59:1: UP030 [*] Use implicit references for positional format fields + | +57 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) +58 | +59 | "{1}_{0}".format(1, 2, *args) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 +60 | +61 | "{1}_{0}".format(1, 2) + | + = help: Remove explicit positional indices + +ℹ Suggested fix +56 56 | +57 57 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) +58 58 | +59 |-"{1}_{0}".format(1, 2, *args) + 59 |+"{}_{}".format(2, 1, ) +60 60 | +61 61 | "{1}_{0}".format(1, 2) + +UP030_0.py:61:1: UP030 [*] Use implicit references for positional format fields + | +59 | "{1}_{0}".format(1, 2, *args) +60 | +61 | "{1}_{0}".format(1, 2) + | ^^^^^^^^^^^^^^^^^^^^^^ UP030 + | + = help: Remove explicit positional indices + +ℹ Suggested fix +58 58 | +59 59 | "{1}_{0}".format(1, 2, *args) +60 60 | +61 |-"{1}_{0}".format(1, 2) + 61 |+"{}_{}".format(2, 1) + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_2.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_2.py.snap deleted file mode 100644 index 7a96569187495..0000000000000 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP030_2.py.snap +++ /dev/null @@ -1,240 +0,0 @@ ---- -source: crates/ruff/src/rules/pyupgrade/mod.rs ---- -UP030_2.py:6:1: UP030 [*] Use implicit references for positional format fields - | -4 | kwargs = {x: x for x in range(10)} -5 | -6 | "{0}".format(*args) - | ^^^^^^^^^^^^^^^^^^^ UP030 -7 | -8 | "{0}".format(**kwargs) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -3 3 | args = list(range(10)) -4 4 | kwargs = {x: x for x in range(10)} -5 5 | -6 |-"{0}".format(*args) - 6 |+"{}".format(*args) -7 7 | -8 8 | "{0}".format(**kwargs) -9 9 | - -UP030_2.py:8:1: UP030 [*] Use implicit references for positional format fields - | - 6 | "{0}".format(*args) - 7 | - 8 | "{0}".format(**kwargs) - | ^^^^^^^^^^^^^^^^^^^^^^ UP030 - 9 | -10 | "{0}_{1}".format(*args) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -5 5 | -6 6 | "{0}".format(*args) -7 7 | -8 |-"{0}".format(**kwargs) - 8 |+"{}".format(**kwargs) -9 9 | -10 10 | "{0}_{1}".format(*args) -11 11 | - -UP030_2.py:10:1: UP030 [*] Use implicit references for positional format fields - | - 8 | "{0}".format(**kwargs) - 9 | -10 | "{0}_{1}".format(*args) - | ^^^^^^^^^^^^^^^^^^^^^^^ UP030 -11 | -12 | "{0}_{1}".format(1, *args) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -7 7 | -8 8 | "{0}".format(**kwargs) -9 9 | -10 |-"{0}_{1}".format(*args) - 10 |+"{}_{}".format(*args) -11 11 | -12 12 | "{0}_{1}".format(1, *args) -13 13 | - -UP030_2.py:12:1: UP030 [*] Use implicit references for positional format fields - | -10 | "{0}_{1}".format(*args) -11 | -12 | "{0}_{1}".format(1, *args) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -13 | -14 | "{1}_{0}".format(*args) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -9 9 | -10 10 | "{0}_{1}".format(*args) -11 11 | -12 |-"{0}_{1}".format(1, *args) - 12 |+"{}_{}".format(1, *args) -13 13 | -14 14 | "{1}_{0}".format(*args) -15 15 | - -UP030_2.py:14:1: UP030 Use implicit references for positional format fields - | -12 | "{0}_{1}".format(1, *args) -13 | -14 | "{1}_{0}".format(*args) - | ^^^^^^^^^^^^^^^^^^^^^^^ UP030 -15 | -16 | "{1}_{0}".format(1, *args) - | - = help: Remove explicit positional indices - -UP030_2.py:16:1: UP030 [*] Use implicit references for positional format fields - | -14 | "{1}_{0}".format(*args) -15 | -16 | "{1}_{0}".format(1, *args) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -17 | -18 | "{0}_{1}".format(1, 2, *args) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -13 13 | -14 14 | "{1}_{0}".format(*args) -15 15 | -16 |-"{1}_{0}".format(1, *args) - 16 |+"{}_{}".format(*args, 1) -17 17 | -18 18 | "{0}_{1}".format(1, 2, *args) -19 19 | - -UP030_2.py:18:1: UP030 [*] Use implicit references for positional format fields - | -16 | "{1}_{0}".format(1, *args) -17 | -18 | "{0}_{1}".format(1, 2, *args) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -19 | -20 | "{0}_{1}".format(*args, 1, 2) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -15 15 | -16 16 | "{1}_{0}".format(1, *args) -17 17 | -18 |-"{0}_{1}".format(1, 2, *args) - 18 |+"{}_{}".format(1, 2, *args) -19 19 | -20 20 | "{0}_{1}".format(*args, 1, 2) -21 21 | - -UP030_2.py:20:1: UP030 [*] Use implicit references for positional format fields - | -18 | "{0}_{1}".format(1, 2, *args) -19 | -20 | "{0}_{1}".format(*args, 1, 2) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -21 | -22 | "{0}_{1}_{2}".format(1, **kwargs) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -17 17 | -18 18 | "{0}_{1}".format(1, 2, *args) -19 19 | -20 |-"{0}_{1}".format(*args, 1, 2) - 20 |+"{}_{}".format(*args, 1, 2) -21 21 | -22 22 | "{0}_{1}_{2}".format(1, **kwargs) -23 23 | - -UP030_2.py:22:1: UP030 [*] Use implicit references for positional format fields - | -20 | "{0}_{1}".format(*args, 1, 2) -21 | -22 | "{0}_{1}_{2}".format(1, **kwargs) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -23 | -24 | "{0}_{1}_{2}".format(1, 2, **kwargs) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -19 19 | -20 20 | "{0}_{1}".format(*args, 1, 2) -21 21 | -22 |-"{0}_{1}_{2}".format(1, **kwargs) - 22 |+"{}_{}_{}".format(1, **kwargs) -23 23 | -24 24 | "{0}_{1}_{2}".format(1, 2, **kwargs) -25 25 | - -UP030_2.py:24:1: UP030 [*] Use implicit references for positional format fields - | -22 | "{0}_{1}_{2}".format(1, **kwargs) -23 | -24 | "{0}_{1}_{2}".format(1, 2, **kwargs) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -25 | -26 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -21 21 | -22 22 | "{0}_{1}_{2}".format(1, **kwargs) -23 23 | -24 |-"{0}_{1}_{2}".format(1, 2, **kwargs) - 24 |+"{}_{}_{}".format(1, 2, **kwargs) -25 25 | -26 26 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) -27 27 | - -UP030_2.py:26:1: UP030 [*] Use implicit references for positional format fields - | -24 | "{0}_{1}_{2}".format(1, 2, **kwargs) -25 | -26 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 -27 | -28 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) - | - = help: Remove explicit positional indices - -ℹ Suggested fix -23 23 | -24 24 | "{0}_{1}_{2}".format(1, 2, **kwargs) -25 25 | -26 |-"{0}_{1}_{2}".format(1, 2, 3, **kwargs) - 26 |+"{}_{}_{}".format(1, 2, 3, **kwargs) -27 27 | -28 28 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) - -UP030_2.py:28:1: UP030 [*] Use implicit references for positional format fields - | -26 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) -27 | -28 | "{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030 - | - = help: Remove explicit positional indices - -ℹ Suggested fix -25 25 | -26 26 | "{0}_{1}_{2}".format(1, 2, 3, **kwargs) -27 27 | -28 |-"{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs) - 28 |+"{}_{}_{}".format(1, 2, 3, *args, **kwargs) - - diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP031_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP031_0.py.snap index 997c209e48e5a..433d011792682 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP031_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP031_0.py.snap @@ -893,5 +893,18 @@ UP031_0.py:104:5: UP031 [*] Use format specifiers instead of percent format 105 |+ foo {} 106 |+ """.format(x) 108 107 | ) +109 108 | +110 109 | "%s" % ( + +UP031_0.py:110:1: UP031 Use format specifiers instead of percent format + | +108 | ) +109 | +110 | / "%s" % ( +111 | | x, # comment +112 | | ) + | |_^ UP031 + | + = help: Replace with format specifiers diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap index 7bda7079a05c7..9daa8f2dbb533 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP032_0.py.snap @@ -29,7 +29,7 @@ UP032_0.py:7:1: UP032 [*] Use f-string instead of `format` call 7 | "{1} {0}".format(a, b) | ^^^^^^^^^^^^^^^^^^^^^^ UP032 8 | -9 | "{x.y}".format(x=z) +9 | "{0} {1} {0}".format(a, b) | = help: Convert to f-string @@ -40,17 +40,17 @@ UP032_0.py:7:1: UP032 [*] Use f-string instead of `format` call 7 |-"{1} {0}".format(a, b) 7 |+f"{b} {a}" 8 8 | -9 9 | "{x.y}".format(x=z) +9 9 | "{0} {1} {0}".format(a, b) 10 10 | UP032_0.py:9:1: UP032 [*] Use f-string instead of `format` call | 7 | "{1} {0}".format(a, b) 8 | - 9 | "{x.y}".format(x=z) - | ^^^^^^^^^^^^^^^^^^^ UP032 + 9 | "{0} {1} {0}".format(a, b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 10 | -11 | "{.x} {.y}".format(a, b) +11 | "{x.y}".format(x=z) | = help: Convert to f-string @@ -58,651 +58,902 @@ UP032_0.py:9:1: UP032 [*] Use f-string instead of `format` call 6 6 | 7 7 | "{1} {0}".format(a, b) 8 8 | -9 |-"{x.y}".format(x=z) - 9 |+f"{z.y}" +9 |-"{0} {1} {0}".format(a, b) + 9 |+f"{a} {b} {a}" 10 10 | -11 11 | "{.x} {.y}".format(a, b) +11 11 | "{x.y}".format(x=z) 12 12 | UP032_0.py:11:1: UP032 [*] Use f-string instead of `format` call | - 9 | "{x.y}".format(x=z) + 9 | "{0} {1} {0}".format(a, b) 10 | -11 | "{.x} {.y}".format(a, b) - | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +11 | "{x.y}".format(x=z) + | ^^^^^^^^^^^^^^^^^^^ UP032 12 | -13 | "{} {}".format(a.b, c.d) +13 | "{x} {y} {x}".format(x=a, y=b) | = help: Convert to f-string ℹ Suggested fix 8 8 | -9 9 | "{x.y}".format(x=z) +9 9 | "{0} {1} {0}".format(a, b) 10 10 | -11 |-"{.x} {.y}".format(a, b) - 11 |+f"{a.x} {b.y}" +11 |-"{x.y}".format(x=z) + 11 |+f"{z.y}" 12 12 | -13 13 | "{} {}".format(a.b, c.d) +13 13 | "{x} {y} {x}".format(x=a, y=b) 14 14 | UP032_0.py:13:1: UP032 [*] Use f-string instead of `format` call | -11 | "{.x} {.y}".format(a, b) +11 | "{x.y}".format(x=z) 12 | -13 | "{} {}".format(a.b, c.d) - | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +13 | "{x} {y} {x}".format(x=a, y=b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 14 | -15 | "{}".format(a()) +15 | "{.x} {.y}".format(a, b) | = help: Convert to f-string ℹ Suggested fix 10 10 | -11 11 | "{.x} {.y}".format(a, b) +11 11 | "{x.y}".format(x=z) 12 12 | -13 |-"{} {}".format(a.b, c.d) - 13 |+f"{a.b} {c.d}" +13 |-"{x} {y} {x}".format(x=a, y=b) + 13 |+f"{a} {b} {a}" 14 14 | -15 15 | "{}".format(a()) +15 15 | "{.x} {.y}".format(a, b) 16 16 | UP032_0.py:15:1: UP032 [*] Use f-string instead of `format` call | -13 | "{} {}".format(a.b, c.d) +13 | "{x} {y} {x}".format(x=a, y=b) 14 | -15 | "{}".format(a()) - | ^^^^^^^^^^^^^^^^ UP032 +15 | "{.x} {.y}".format(a, b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 16 | -17 | "{}".format(a.b()) +17 | "{} {}".format(a.b, c.d) | = help: Convert to f-string ℹ Suggested fix 12 12 | -13 13 | "{} {}".format(a.b, c.d) +13 13 | "{x} {y} {x}".format(x=a, y=b) 14 14 | -15 |-"{}".format(a()) - 15 |+f"{a()}" +15 |-"{.x} {.y}".format(a, b) + 15 |+f"{a.x} {b.y}" 16 16 | -17 17 | "{}".format(a.b()) +17 17 | "{} {}".format(a.b, c.d) 18 18 | UP032_0.py:17:1: UP032 [*] Use f-string instead of `format` call | -15 | "{}".format(a()) +15 | "{.x} {.y}".format(a, b) 16 | -17 | "{}".format(a.b()) - | ^^^^^^^^^^^^^^^^^^ UP032 +17 | "{} {}".format(a.b, c.d) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 18 | -19 | "{}".format(a.b().c()) +19 | "{}".format(a()) | = help: Convert to f-string ℹ Suggested fix 14 14 | -15 15 | "{}".format(a()) +15 15 | "{.x} {.y}".format(a, b) 16 16 | -17 |-"{}".format(a.b()) - 17 |+f"{a.b()}" +17 |-"{} {}".format(a.b, c.d) + 17 |+f"{a.b} {c.d}" 18 18 | -19 19 | "{}".format(a.b().c()) +19 19 | "{}".format(a()) 20 20 | UP032_0.py:19:1: UP032 [*] Use f-string instead of `format` call | -17 | "{}".format(a.b()) +17 | "{} {}".format(a.b, c.d) 18 | -19 | "{}".format(a.b().c()) - | ^^^^^^^^^^^^^^^^^^^^^^ UP032 +19 | "{}".format(a()) + | ^^^^^^^^^^^^^^^^ UP032 20 | -21 | "hello {}!".format(name) +21 | "{}".format(a.b()) | = help: Convert to f-string ℹ Suggested fix 16 16 | -17 17 | "{}".format(a.b()) +17 17 | "{} {}".format(a.b, c.d) 18 18 | -19 |-"{}".format(a.b().c()) - 19 |+f"{a.b().c()}" +19 |-"{}".format(a()) + 19 |+f"{a()}" 20 20 | -21 21 | "hello {}!".format(name) +21 21 | "{}".format(a.b()) 22 22 | UP032_0.py:21:1: UP032 [*] Use f-string instead of `format` call | -19 | "{}".format(a.b().c()) +19 | "{}".format(a()) 20 | -21 | "hello {}!".format(name) - | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +21 | "{}".format(a.b()) + | ^^^^^^^^^^^^^^^^^^ UP032 22 | -23 | "{}{b}{}".format(a, c, b=b) +23 | "{}".format(a.b().c()) | = help: Convert to f-string ℹ Suggested fix 18 18 | -19 19 | "{}".format(a.b().c()) +19 19 | "{}".format(a()) 20 20 | -21 |-"hello {}!".format(name) - 21 |+f"hello {name}!" +21 |-"{}".format(a.b()) + 21 |+f"{a.b()}" 22 22 | -23 23 | "{}{b}{}".format(a, c, b=b) +23 23 | "{}".format(a.b().c()) 24 24 | UP032_0.py:23:1: UP032 [*] Use f-string instead of `format` call | -21 | "hello {}!".format(name) +21 | "{}".format(a.b()) 22 | -23 | "{}{b}{}".format(a, c, b=b) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +23 | "{}".format(a.b().c()) + | ^^^^^^^^^^^^^^^^^^^^^^ UP032 24 | -25 | "{}".format(0x0) +25 | "hello {}!".format(name) | = help: Convert to f-string ℹ Suggested fix 20 20 | -21 21 | "hello {}!".format(name) +21 21 | "{}".format(a.b()) 22 22 | -23 |-"{}{b}{}".format(a, c, b=b) - 23 |+f"{a}{b}{c}" +23 |-"{}".format(a.b().c()) + 23 |+f"{a.b().c()}" 24 24 | -25 25 | "{}".format(0x0) +25 25 | "hello {}!".format(name) 26 26 | UP032_0.py:25:1: UP032 [*] Use f-string instead of `format` call | -23 | "{}{b}{}".format(a, c, b=b) +23 | "{}".format(a.b().c()) 24 | -25 | "{}".format(0x0) - | ^^^^^^^^^^^^^^^^ UP032 +25 | "hello {}!".format(name) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 26 | -27 | "{} {}".format(a, b) +27 | "{}{b}{}".format(a, c, b=b) | = help: Convert to f-string ℹ Suggested fix 22 22 | -23 23 | "{}{b}{}".format(a, c, b=b) +23 23 | "{}".format(a.b().c()) 24 24 | -25 |-"{}".format(0x0) - 25 |+f"{0x0}" +25 |-"hello {}!".format(name) + 25 |+f"hello {name}!" 26 26 | -27 27 | "{} {}".format(a, b) +27 27 | "{}{b}{}".format(a, c, b=b) 28 28 | UP032_0.py:27:1: UP032 [*] Use f-string instead of `format` call | -25 | "{}".format(0x0) +25 | "hello {}!".format(name) 26 | -27 | "{} {}".format(a, b) - | ^^^^^^^^^^^^^^^^^^^^ UP032 +27 | "{}{b}{}".format(a, c, b=b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 28 | -29 | """{} {}""".format(a, b) +29 | "{}".format(0x0) | = help: Convert to f-string ℹ Suggested fix 24 24 | -25 25 | "{}".format(0x0) +25 25 | "hello {}!".format(name) 26 26 | -27 |-"{} {}".format(a, b) - 27 |+f"{a} {b}" +27 |-"{}{b}{}".format(a, c, b=b) + 27 |+f"{a}{b}{c}" 28 28 | -29 29 | """{} {}""".format(a, b) +29 29 | "{}".format(0x0) 30 30 | UP032_0.py:29:1: UP032 [*] Use f-string instead of `format` call | -27 | "{} {}".format(a, b) +27 | "{}{b}{}".format(a, c, b=b) 28 | -29 | """{} {}""".format(a, b) - | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +29 | "{}".format(0x0) + | ^^^^^^^^^^^^^^^^ UP032 30 | -31 | "foo{}".format(1) +31 | "{} {}".format(a, b) | = help: Convert to f-string ℹ Suggested fix 26 26 | -27 27 | "{} {}".format(a, b) +27 27 | "{}{b}{}".format(a, c, b=b) 28 28 | -29 |-"""{} {}""".format(a, b) - 29 |+f"""{a} {b}""" +29 |-"{}".format(0x0) + 29 |+f"{0x0}" 30 30 | -31 31 | "foo{}".format(1) +31 31 | "{} {}".format(a, b) 32 32 | UP032_0.py:31:1: UP032 [*] Use f-string instead of `format` call | -29 | """{} {}""".format(a, b) +29 | "{}".format(0x0) 30 | -31 | "foo{}".format(1) - | ^^^^^^^^^^^^^^^^^ UP032 +31 | "{} {}".format(a, b) + | ^^^^^^^^^^^^^^^^^^^^ UP032 32 | -33 | r"foo{}".format(1) +33 | """{} {}""".format(a, b) | = help: Convert to f-string ℹ Suggested fix 28 28 | -29 29 | """{} {}""".format(a, b) +29 29 | "{}".format(0x0) 30 30 | -31 |-"foo{}".format(1) - 31 |+f"foo{1}" +31 |-"{} {}".format(a, b) + 31 |+f"{a} {b}" 32 32 | -33 33 | r"foo{}".format(1) +33 33 | """{} {}""".format(a, b) 34 34 | UP032_0.py:33:1: UP032 [*] Use f-string instead of `format` call | -31 | "foo{}".format(1) +31 | "{} {}".format(a, b) 32 | -33 | r"foo{}".format(1) - | ^^^^^^^^^^^^^^^^^^ UP032 +33 | """{} {}""".format(a, b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 34 | -35 | x = "{a}".format(a=1) +35 | "foo{}".format(1) | = help: Convert to f-string ℹ Suggested fix 30 30 | -31 31 | "foo{}".format(1) +31 31 | "{} {}".format(a, b) 32 32 | -33 |-r"foo{}".format(1) - 33 |+fr"foo{1}" +33 |-"""{} {}""".format(a, b) + 33 |+f"""{a} {b}""" 34 34 | -35 35 | x = "{a}".format(a=1) +35 35 | "foo{}".format(1) 36 36 | -UP032_0.py:35:5: UP032 [*] Use f-string instead of `format` call +UP032_0.py:35:1: UP032 [*] Use f-string instead of `format` call | -33 | r"foo{}".format(1) +33 | """{} {}""".format(a, b) 34 | -35 | x = "{a}".format(a=1) - | ^^^^^^^^^^^^^^^^^ UP032 +35 | "foo{}".format(1) + | ^^^^^^^^^^^^^^^^^ UP032 36 | -37 | print("foo {} ".format(x)) +37 | r"foo{}".format(1) | = help: Convert to f-string ℹ Suggested fix 32 32 | -33 33 | r"foo{}".format(1) +33 33 | """{} {}""".format(a, b) 34 34 | -35 |-x = "{a}".format(a=1) - 35 |+x = f"{1}" +35 |-"foo{}".format(1) + 35 |+f"foo{1}" 36 36 | -37 37 | print("foo {} ".format(x)) +37 37 | r"foo{}".format(1) 38 38 | -UP032_0.py:37:7: UP032 [*] Use f-string instead of `format` call +UP032_0.py:37:1: UP032 [*] Use f-string instead of `format` call | -35 | x = "{a}".format(a=1) +35 | "foo{}".format(1) 36 | -37 | print("foo {} ".format(x)) - | ^^^^^^^^^^^^^^^^^^^ UP032 +37 | r"foo{}".format(1) + | ^^^^^^^^^^^^^^^^^^ UP032 38 | -39 | "{a[b]}".format(a=a) +39 | x = "{a}".format(a=1) | = help: Convert to f-string ℹ Suggested fix 34 34 | -35 35 | x = "{a}".format(a=1) +35 35 | "foo{}".format(1) 36 36 | -37 |-print("foo {} ".format(x)) - 37 |+print(f"foo {x} ") +37 |-r"foo{}".format(1) + 37 |+fr"foo{1}" 38 38 | -39 39 | "{a[b]}".format(a=a) +39 39 | x = "{a}".format(a=1) 40 40 | -UP032_0.py:39:1: UP032 [*] Use f-string instead of `format` call +UP032_0.py:39:5: UP032 [*] Use f-string instead of `format` call | -37 | print("foo {} ".format(x)) +37 | r"foo{}".format(1) 38 | -39 | "{a[b]}".format(a=a) - | ^^^^^^^^^^^^^^^^^^^^ UP032 +39 | x = "{a}".format(a=1) + | ^^^^^^^^^^^^^^^^^ UP032 40 | -41 | "{a.a[b]}".format(a=a) +41 | print("foo {} ".format(x)) | = help: Convert to f-string ℹ Suggested fix 36 36 | -37 37 | print("foo {} ".format(x)) +37 37 | r"foo{}".format(1) 38 38 | -39 |-"{a[b]}".format(a=a) - 39 |+f"{a['b']}" +39 |-x = "{a}".format(a=1) + 39 |+x = f"{1}" 40 40 | -41 41 | "{a.a[b]}".format(a=a) +41 41 | print("foo {} ".format(x)) 42 42 | -UP032_0.py:41:1: UP032 [*] Use f-string instead of `format` call +UP032_0.py:41:7: UP032 [*] Use f-string instead of `format` call | -39 | "{a[b]}".format(a=a) +39 | x = "{a}".format(a=1) 40 | -41 | "{a.a[b]}".format(a=a) - | ^^^^^^^^^^^^^^^^^^^^^^ UP032 +41 | print("foo {} ".format(x)) + | ^^^^^^^^^^^^^^^^^^^ UP032 42 | -43 | "{}{{}}{}".format(escaped, y) +43 | "{a[b]}".format(a=a) | = help: Convert to f-string ℹ Suggested fix 38 38 | -39 39 | "{a[b]}".format(a=a) +39 39 | x = "{a}".format(a=1) 40 40 | -41 |-"{a.a[b]}".format(a=a) - 41 |+f"{a.a['b']}" +41 |-print("foo {} ".format(x)) + 41 |+print(f"foo {x} ") 42 42 | -43 43 | "{}{{}}{}".format(escaped, y) +43 43 | "{a[b]}".format(a=a) 44 44 | UP032_0.py:43:1: UP032 [*] Use f-string instead of `format` call | -41 | "{a.a[b]}".format(a=a) +41 | print("foo {} ".format(x)) 42 | -43 | "{}{{}}{}".format(escaped, y) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +43 | "{a[b]}".format(a=a) + | ^^^^^^^^^^^^^^^^^^^^ UP032 44 | -45 | "{}".format(a) +45 | "{a.a[b]}".format(a=a) | = help: Convert to f-string ℹ Suggested fix 40 40 | -41 41 | "{a.a[b]}".format(a=a) +41 41 | print("foo {} ".format(x)) 42 42 | -43 |-"{}{{}}{}".format(escaped, y) - 43 |+f"{escaped}{{}}{y}" +43 |-"{a[b]}".format(a=a) + 43 |+f"{a['b']}" 44 44 | -45 45 | "{}".format(a) +45 45 | "{a.a[b]}".format(a=a) 46 46 | UP032_0.py:45:1: UP032 [*] Use f-string instead of `format` call | -43 | "{}{{}}{}".format(escaped, y) +43 | "{a[b]}".format(a=a) 44 | -45 | "{}".format(a) - | ^^^^^^^^^^^^^^ UP032 +45 | "{a.a[b]}".format(a=a) + | ^^^^^^^^^^^^^^^^^^^^^^ UP032 46 | -47 | '({}={{0!e}})'.format(a) +47 | "{}{{}}{}".format(escaped, y) | = help: Convert to f-string ℹ Suggested fix 42 42 | -43 43 | "{}{{}}{}".format(escaped, y) +43 43 | "{a[b]}".format(a=a) 44 44 | -45 |-"{}".format(a) - 45 |+f"{a}" +45 |-"{a.a[b]}".format(a=a) + 45 |+f"{a.a['b']}" 46 46 | -47 47 | '({}={{0!e}})'.format(a) +47 47 | "{}{{}}{}".format(escaped, y) 48 48 | UP032_0.py:47:1: UP032 [*] Use f-string instead of `format` call | -45 | "{}".format(a) +45 | "{a.a[b]}".format(a=a) 46 | -47 | '({}={{0!e}})'.format(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +47 | "{}{{}}{}".format(escaped, y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 48 | -49 | "{[b]}".format(a) +49 | "{}".format(a) | = help: Convert to f-string ℹ Suggested fix 44 44 | -45 45 | "{}".format(a) +45 45 | "{a.a[b]}".format(a=a) 46 46 | -47 |-'({}={{0!e}})'.format(a) - 47 |+f'({a}={{0!e}})' +47 |-"{}{{}}{}".format(escaped, y) + 47 |+f"{escaped}{{}}{y}" 48 48 | -49 49 | "{[b]}".format(a) +49 49 | "{}".format(a) 50 50 | UP032_0.py:49:1: UP032 [*] Use f-string instead of `format` call | -47 | '({}={{0!e}})'.format(a) +47 | "{}{{}}{}".format(escaped, y) 48 | -49 | "{[b]}".format(a) - | ^^^^^^^^^^^^^^^^^ UP032 +49 | "{}".format(a) + | ^^^^^^^^^^^^^^ UP032 50 | -51 | '{[b]}'.format(a) +51 | '({}={{0!e}})'.format(a) | = help: Convert to f-string ℹ Suggested fix 46 46 | -47 47 | '({}={{0!e}})'.format(a) +47 47 | "{}{{}}{}".format(escaped, y) 48 48 | -49 |-"{[b]}".format(a) - 49 |+f"{a['b']}" +49 |-"{}".format(a) + 49 |+f"{a}" 50 50 | -51 51 | '{[b]}'.format(a) +51 51 | '({}={{0!e}})'.format(a) 52 52 | UP032_0.py:51:1: UP032 [*] Use f-string instead of `format` call | -49 | "{[b]}".format(a) +49 | "{}".format(a) 50 | -51 | '{[b]}'.format(a) - | ^^^^^^^^^^^^^^^^^ UP032 +51 | '({}={{0!e}})'.format(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 52 | -53 | """{[b]}""".format(a) +53 | "{[b]}".format(a) | = help: Convert to f-string ℹ Suggested fix 48 48 | -49 49 | "{[b]}".format(a) +49 49 | "{}".format(a) 50 50 | -51 |-'{[b]}'.format(a) - 51 |+f'{a["b"]}' +51 |-'({}={{0!e}})'.format(a) + 51 |+f'({a}={{0!e}})' 52 52 | -53 53 | """{[b]}""".format(a) +53 53 | "{[b]}".format(a) 54 54 | UP032_0.py:53:1: UP032 [*] Use f-string instead of `format` call | -51 | '{[b]}'.format(a) +51 | '({}={{0!e}})'.format(a) 52 | -53 | """{[b]}""".format(a) - | ^^^^^^^^^^^^^^^^^^^^^ UP032 +53 | "{[b]}".format(a) + | ^^^^^^^^^^^^^^^^^ UP032 54 | -55 | '''{[b]}'''.format(a) +55 | '{[b]}'.format(a) | = help: Convert to f-string ℹ Suggested fix 50 50 | -51 51 | '{[b]}'.format(a) +51 51 | '({}={{0!e}})'.format(a) 52 52 | -53 |-"""{[b]}""".format(a) - 53 |+f"""{a["b"]}""" +53 |-"{[b]}".format(a) + 53 |+f"{a['b']}" 54 54 | -55 55 | '''{[b]}'''.format(a) +55 55 | '{[b]}'.format(a) 56 56 | UP032_0.py:55:1: UP032 [*] Use f-string instead of `format` call | -53 | """{[b]}""".format(a) +53 | "{[b]}".format(a) 54 | -55 | '''{[b]}'''.format(a) - | ^^^^^^^^^^^^^^^^^^^^^ UP032 +55 | '{[b]}'.format(a) + | ^^^^^^^^^^^^^^^^^ UP032 56 | -57 | "{}".format( +57 | """{[b]}""".format(a) | = help: Convert to f-string ℹ Suggested fix 52 52 | -53 53 | """{[b]}""".format(a) +53 53 | "{[b]}".format(a) 54 54 | -55 |-'''{[b]}'''.format(a) - 55 |+f'''{a["b"]}''' +55 |-'{[b]}'.format(a) + 55 |+f'{a["b"]}' 56 56 | -57 57 | "{}".format( -58 58 | 1 +57 57 | """{[b]}""".format(a) +58 58 | UP032_0.py:57:1: UP032 [*] Use f-string instead of `format` call | -55 | '''{[b]}'''.format(a) -56 | -57 | / "{}".format( -58 | | 1 -59 | | ) - | |_^ UP032 -60 | -61 | "123456789 {}".format( +55 | '{[b]}'.format(a) +56 | +57 | """{[b]}""".format(a) + | ^^^^^^^^^^^^^^^^^^^^^ UP032 +58 | +59 | '''{[b]}'''.format(a) | = help: Convert to f-string ℹ Suggested fix 54 54 | -55 55 | '''{[b]}'''.format(a) +55 55 | '{[b]}'.format(a) 56 56 | -57 |-"{}".format( -58 |- 1 -59 |-) - 57 |+f"{1}" -60 58 | -61 59 | "123456789 {}".format( -62 60 | 1111111111111111111111111111111111111111111111111111111111111111111111111, +57 |-"""{[b]}""".format(a) + 57 |+f"""{a["b"]}""" +58 58 | +59 59 | '''{[b]}'''.format(a) +60 60 | + +UP032_0.py:59:1: UP032 [*] Use f-string instead of `format` call + | +57 | """{[b]}""".format(a) +58 | +59 | '''{[b]}'''.format(a) + | ^^^^^^^^^^^^^^^^^^^^^ UP032 +60 | +61 | "{}".format( + | + = help: Convert to f-string + +ℹ Suggested fix +56 56 | +57 57 | """{[b]}""".format(a) +58 58 | +59 |-'''{[b]}'''.format(a) + 59 |+f'''{a["b"]}''' +60 60 | +61 61 | "{}".format( +62 62 | 1 UP032_0.py:61:1: UP032 [*] Use f-string instead of `format` call | -59 | ) +59 | '''{[b]}'''.format(a) 60 | -61 | / "123456789 {}".format( -62 | | 1111111111111111111111111111111111111111111111111111111111111111111111111, +61 | / "{}".format( +62 | | 1 63 | | ) | |_^ UP032 64 | -65 | """ +65 | "123456789 {}".format( | = help: Convert to f-string ℹ Suggested fix -58 58 | 1 -59 59 | ) +58 58 | +59 59 | '''{[b]}'''.format(a) 60 60 | -61 |-"123456789 {}".format( -62 |- 1111111111111111111111111111111111111111111111111111111111111111111111111, +61 |-"{}".format( +62 |- 1 63 |-) - 61 |+f"123456789 {1111111111111111111111111111111111111111111111111111111111111111111111111}" + 61 |+f"{1}" 64 62 | -65 63 | """ -66 64 | {} +65 63 | "123456789 {}".format( +66 64 | 1111111111111111111111111111111111111111111111111111111111111111111111111, UP032_0.py:65:1: UP032 [*] Use f-string instead of `format` call | 63 | ) 64 | -65 | / """ -66 | | {} -67 | | """.format(1) - | |_____________^ UP032 +65 | / "123456789 {}".format( +66 | | 1111111111111111111111111111111111111111111111111111111111111111111111111, +67 | | ) + | |_^ UP032 68 | -69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +69 | """ | = help: Convert to f-string ℹ Suggested fix -62 62 | 1111111111111111111111111111111111111111111111111111111111111111111111111, +62 62 | 1 63 63 | ) 64 64 | - 65 |+f""" - 66 |+{1} -65 67 | """ -66 |-{} -67 |-""".format(1) -68 68 | -69 69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ -70 70 | {} +65 |-"123456789 {}".format( +66 |- 1111111111111111111111111111111111111111111111111111111111111111111111111, +67 |-) + 65 |+f"123456789 {1111111111111111111111111111111111111111111111111111111111111111111111111}" +68 66 | +69 67 | """ +70 68 | {} -UP032_0.py:69:85: UP032 [*] Use f-string instead of `format` call +UP032_0.py:69:1: UP032 [*] Use f-string instead of `format` call | -67 | """.format(1) +67 | ) 68 | -69 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ - | _____________________________________________________________________________________^ +69 | / """ 70 | | {} -71 | | """.format( -72 | | 111111 -73 | | ) - | |_^ UP032 -74 | -75 | ### +71 | | """.format(1) + | |_____________^ UP032 +72 | +73 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ | = help: Convert to f-string ℹ Suggested fix -66 66 | {} -67 67 | """.format(1) +66 66 | 1111111111111111111111111111111111111111111111111111111111111111111111111, +67 67 | ) 68 68 | -69 |-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ + 69 |+f""" + 70 |+{1} +69 71 | """ 70 |-{} -71 |-""".format( -72 |- 111111 -73 |-) - 69 |+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = f""" - 70 |+{111111} - 71 |+""" -74 72 | -75 73 | ### -76 74 | # Non-errors - -UP032_0.py:152:11: UP032 [*] Use f-string instead of `format` call +71 |-""".format(1) +72 72 | +73 73 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +74 74 | {} + +UP032_0.py:73:85: UP032 [*] Use f-string instead of `format` call + | +71 | """.format(1) +72 | +73 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ + | _____________________________________________________________________________________^ +74 | | {} +75 | | """.format( +76 | | 111111 +77 | | ) + | |_^ UP032 +78 | +79 | "{a}" "{b}".format(a=1, b=1) + | + = help: Convert to f-string + +ℹ Suggested fix +70 70 | {} +71 71 | """.format(1) +72 72 | +73 |-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = """ +74 |-{} +75 |-""".format( +76 |- 111111 +77 |-) + 73 |+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = f""" + 74 |+{111111} + 75 |+""" +78 76 | +79 77 | "{a}" "{b}".format(a=1, b=1) +80 78 | + +UP032_0.py:79:1: UP032 [*] Use f-string instead of `format` call + | +77 | ) +78 | +79 | "{a}" "{b}".format(a=1, b=1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 +80 | +81 | ( + | + = help: Convert to f-string + +ℹ Suggested fix +76 76 | 111111 +77 77 | ) +78 78 | +79 |-"{a}" "{b}".format(a=1, b=1) + 79 |+f"{1}" f"{1}" +80 80 | +81 81 | ( +82 82 | "{a}" + +UP032_0.py:81:1: UP032 [*] Use f-string instead of `format` call + | +79 | "{a}" "{b}".format(a=1, b=1) +80 | +81 | / ( +82 | | "{a}" +83 | | "{b}" +84 | | ).format(a=1, b=1) + | |__________________^ UP032 +85 | +86 | ( + | + = help: Convert to f-string + +ℹ Suggested fix +79 79 | "{a}" "{b}".format(a=1, b=1) +80 80 | +81 81 | ( +82 |- "{a}" +83 |- "{b}" +84 |-).format(a=1, b=1) + 82 |+ f"{1}" + 83 |+ f"{1}" + 84 |+) +85 85 | +86 86 | ( +87 87 | "{a}" + +UP032_0.py:86:1: UP032 [*] Use f-string instead of `format` call + | +84 | ).format(a=1, b=1) +85 | +86 | / ( +87 | | "{a}" +88 | | "" +89 | | "{b}" +90 | | "" +91 | | ).format(a=1, b=1) + | |__________________^ UP032 +92 | +93 | ( + | + = help: Convert to f-string + +ℹ Suggested fix +84 84 | ).format(a=1, b=1) +85 85 | +86 86 | ( +87 |- "{a}" + 87 |+ f"{1}" +88 88 | "" +89 |- "{b}" + 89 |+ f"{1}" +90 90 | "" +91 |-).format(a=1, b=1) + 91 |+) +92 92 | +93 93 | ( +94 94 | ( + +UP032_0.py:94:5: UP032 [*] Use f-string instead of `format` call | -151 | def d(osname, version, release): -152 | return"{}-{}.{}".format(osname, version, release) + 93 | ( + 94 | ( + | _____^ + 95 | | # comment + 96 | | "{a}" + 97 | | # comment + 98 | | "{b}" + 99 | | ) +100 | | # comment +101 | | .format(a=1, b=1) + | |_____________________^ UP032 +102 | ) + | + = help: Convert to f-string + +ℹ Suggested fix +93 93 | ( +94 94 | ( +95 95 | # comment +96 |- "{a}" + 96 |+ f"{1}" +97 97 | # comment +98 |- "{b}" + 98 |+ f"{1}" +99 99 | ) +100 100 | # comment +101 |- .format(a=1, b=1) + 101 |+ +102 102 | ) +103 103 | +104 104 | ( + +UP032_0.py:104:1: UP032 [*] Use f-string instead of `format` call + | +102 | ) +103 | +104 | / ( +105 | | "{a}" +106 | | "b" +107 | | ).format(a=1) + | |_____________^ UP032 + | + = help: Convert to f-string + +ℹ Suggested fix +102 102 | ) +103 103 | +104 104 | ( +105 |- "{a}" + 105 |+ f"{1}" +106 106 | "b" +107 |-).format(a=1) + 107 |+) +108 108 | +109 109 | +110 110 | def d(osname, version, release): + +UP032_0.py:111:11: UP032 [*] Use f-string instead of `format` call + | +110 | def d(osname, version, release): +111 | return"{}-{}.{}".format(osname, version, release) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -149 149 | -150 150 | -151 151 | def d(osname, version, release): -152 |- return"{}-{}.{}".format(osname, version, release) - 152 |+ return f"{osname}-{version}.{release}" -153 153 | -154 154 | -155 155 | def e(): +108 108 | +109 109 | +110 110 | def d(osname, version, release): +111 |- return"{}-{}.{}".format(osname, version, release) + 111 |+ return f"{osname}-{version}.{release}" +112 112 | +113 113 | +114 114 | def e(): -UP032_0.py:156:10: UP032 [*] Use f-string instead of `format` call +UP032_0.py:115:10: UP032 [*] Use f-string instead of `format` call | -155 | def e(): -156 | yield"{}".format(1) +114 | def e(): +115 | yield"{}".format(1) | ^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -153 153 | -154 154 | -155 155 | def e(): -156 |- yield"{}".format(1) - 156 |+ yield f"{1}" -157 157 | -158 158 | -159 159 | assert"{}".format(1) +112 112 | +113 113 | +114 114 | def e(): +115 |- yield"{}".format(1) + 115 |+ yield f"{1}" +116 116 | +117 117 | +118 118 | assert"{}".format(1) -UP032_0.py:159:7: UP032 [*] Use f-string instead of `format` call +UP032_0.py:118:7: UP032 [*] Use f-string instead of `format` call | -159 | assert"{}".format(1) +118 | assert"{}".format(1) | ^^^^^^^^^^^^^^ UP032 | = help: Convert to f-string ℹ Suggested fix -156 156 | yield"{}".format(1) -157 157 | -158 158 | -159 |-assert"{}".format(1) - 159 |+assert f"{1}" +115 115 | yield"{}".format(1) +116 116 | +117 117 | +118 |-assert"{}".format(1) + 118 |+assert f"{1}" +119 119 | +120 120 | +121 121 | async def c(): + +UP032_0.py:122:12: UP032 [*] Use f-string instead of `format` call + | +121 | async def c(): +122 | return "{}".format(await 3) + | ^^^^^^^^^^^^^^^^^^^^ UP032 + | + = help: Convert to f-string + +ℹ Suggested fix +119 119 | +120 120 | +121 121 | async def c(): +122 |- return "{}".format(await 3) + 122 |+ return f"{await 3}" +123 123 | +124 124 | +125 125 | async def c(): + +UP032_0.py:126:12: UP032 [*] Use f-string instead of `format` call + | +125 | async def c(): +126 | return "{}".format(1 + await 3) + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP032 + | + = help: Convert to f-string + +ℹ Suggested fix +123 123 | +124 124 | +125 125 | async def c(): +126 |- return "{}".format(1 + await 3) + 126 |+ return f"{1 + await 3}" +127 127 | +128 128 | +129 129 | "{}".format(1 * 2) + +UP032_0.py:129:1: UP032 [*] Use f-string instead of `format` call + | +129 | "{}".format(1 * 2) + | ^^^^^^^^^^^^^^^^^^ UP032 +130 | +131 | ### + | + = help: Convert to f-string + +ℹ Suggested fix +126 126 | return "{}".format(1 + await 3) +127 127 | +128 128 | +129 |-"{}".format(1 * 2) + 129 |+f"{1 * 2}" +130 130 | +131 131 | ### +132 132 | # Non-errors + +UP032_0.py:202:1: UP032 Use f-string instead of `format` call + | +200 | "{}".format(**c) +201 | +202 | / "{}".format( +203 | | 1 # comment +204 | | ) + | |_^ UP032 + | + = help: Convert to f-string diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap index e9c2076aeddd5..04319f36dc70b 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap @@ -416,8 +416,577 @@ UP035.py:46:10: UP035 Import from `collections.abc` instead: `Mapping` 47 | | Mapping, Counter) | |_____________________^ UP035 48 | -49 | # OK +49 | # Bad imports from PYI027 that are now handled by PYI022 (UP035) | = help: Import from `collections.abc` +UP035.py:50:1: UP035 `typing.ContextManager` is deprecated, use `contextlib.AbstractContextManager` instead + | +49 | # Bad imports from PYI027 that are now handled by PYI022 (UP035) +50 | from typing import ContextManager + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +51 | from typing import OrderedDict +52 | from typing_extensions import OrderedDict + | + +UP035.py:51:1: UP035 [*] Import from `collections` instead: `OrderedDict` + | +49 | # Bad imports from PYI027 that are now handled by PYI022 (UP035) +50 | from typing import ContextManager +51 | from typing import OrderedDict + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +52 | from typing_extensions import OrderedDict +53 | from typing import Callable + | + = help: Import from `collections` + +ℹ Suggested fix +48 48 | +49 49 | # Bad imports from PYI027 that are now handled by PYI022 (UP035) +50 50 | from typing import ContextManager +51 |-from typing import OrderedDict + 51 |+from collections import OrderedDict +52 52 | from typing_extensions import OrderedDict +53 53 | from typing import Callable +54 54 | from typing import ByteString + +UP035.py:52:1: UP035 [*] Import from `typing` instead: `OrderedDict` + | +50 | from typing import ContextManager +51 | from typing import OrderedDict +52 | from typing_extensions import OrderedDict + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +53 | from typing import Callable +54 | from typing import ByteString + | + = help: Import from `typing` + +ℹ Suggested fix +49 49 | # Bad imports from PYI027 that are now handled by PYI022 (UP035) +50 50 | from typing import ContextManager +51 51 | from typing import OrderedDict +52 |-from typing_extensions import OrderedDict + 52 |+from typing import OrderedDict +53 53 | from typing import Callable +54 54 | from typing import ByteString +55 55 | from typing import Container + +UP035.py:53:1: UP035 [*] Import from `collections.abc` instead: `Callable` + | +51 | from typing import OrderedDict +52 | from typing_extensions import OrderedDict +53 | from typing import Callable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +54 | from typing import ByteString +55 | from typing import Container + | + = help: Import from `collections.abc` + +ℹ Suggested fix +50 50 | from typing import ContextManager +51 51 | from typing import OrderedDict +52 52 | from typing_extensions import OrderedDict +53 |-from typing import Callable + 53 |+from collections.abc import Callable +54 54 | from typing import ByteString +55 55 | from typing import Container +56 56 | from typing import Hashable + +UP035.py:54:1: UP035 [*] Import from `collections.abc` instead: `ByteString` + | +52 | from typing_extensions import OrderedDict +53 | from typing import Callable +54 | from typing import ByteString + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +55 | from typing import Container +56 | from typing import Hashable + | + = help: Import from `collections.abc` + +ℹ Suggested fix +51 51 | from typing import OrderedDict +52 52 | from typing_extensions import OrderedDict +53 53 | from typing import Callable +54 |-from typing import ByteString + 54 |+from collections.abc import ByteString +55 55 | from typing import Container +56 56 | from typing import Hashable +57 57 | from typing import ItemsView + +UP035.py:55:1: UP035 [*] Import from `collections.abc` instead: `Container` + | +53 | from typing import Callable +54 | from typing import ByteString +55 | from typing import Container + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +56 | from typing import Hashable +57 | from typing import ItemsView + | + = help: Import from `collections.abc` + +ℹ Suggested fix +52 52 | from typing_extensions import OrderedDict +53 53 | from typing import Callable +54 54 | from typing import ByteString +55 |-from typing import Container + 55 |+from collections.abc import Container +56 56 | from typing import Hashable +57 57 | from typing import ItemsView +58 58 | from typing import Iterable + +UP035.py:56:1: UP035 [*] Import from `collections.abc` instead: `Hashable` + | +54 | from typing import ByteString +55 | from typing import Container +56 | from typing import Hashable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +57 | from typing import ItemsView +58 | from typing import Iterable + | + = help: Import from `collections.abc` + +ℹ Suggested fix +53 53 | from typing import Callable +54 54 | from typing import ByteString +55 55 | from typing import Container +56 |-from typing import Hashable + 56 |+from collections.abc import Hashable +57 57 | from typing import ItemsView +58 58 | from typing import Iterable +59 59 | from typing import Iterator + +UP035.py:57:1: UP035 [*] Import from `collections.abc` instead: `ItemsView` + | +55 | from typing import Container +56 | from typing import Hashable +57 | from typing import ItemsView + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +58 | from typing import Iterable +59 | from typing import Iterator + | + = help: Import from `collections.abc` + +ℹ Suggested fix +54 54 | from typing import ByteString +55 55 | from typing import Container +56 56 | from typing import Hashable +57 |-from typing import ItemsView + 57 |+from collections.abc import ItemsView +58 58 | from typing import Iterable +59 59 | from typing import Iterator +60 60 | from typing import KeysView + +UP035.py:58:1: UP035 [*] Import from `collections.abc` instead: `Iterable` + | +56 | from typing import Hashable +57 | from typing import ItemsView +58 | from typing import Iterable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +59 | from typing import Iterator +60 | from typing import KeysView + | + = help: Import from `collections.abc` + +ℹ Suggested fix +55 55 | from typing import Container +56 56 | from typing import Hashable +57 57 | from typing import ItemsView +58 |-from typing import Iterable + 58 |+from collections.abc import Iterable +59 59 | from typing import Iterator +60 60 | from typing import KeysView +61 61 | from typing import Mapping + +UP035.py:59:1: UP035 [*] Import from `collections.abc` instead: `Iterator` + | +57 | from typing import ItemsView +58 | from typing import Iterable +59 | from typing import Iterator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +60 | from typing import KeysView +61 | from typing import Mapping + | + = help: Import from `collections.abc` + +ℹ Suggested fix +56 56 | from typing import Hashable +57 57 | from typing import ItemsView +58 58 | from typing import Iterable +59 |-from typing import Iterator + 59 |+from collections.abc import Iterator +60 60 | from typing import KeysView +61 61 | from typing import Mapping +62 62 | from typing import MappingView + +UP035.py:60:1: UP035 [*] Import from `collections.abc` instead: `KeysView` + | +58 | from typing import Iterable +59 | from typing import Iterator +60 | from typing import KeysView + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +61 | from typing import Mapping +62 | from typing import MappingView + | + = help: Import from `collections.abc` + +ℹ Suggested fix +57 57 | from typing import ItemsView +58 58 | from typing import Iterable +59 59 | from typing import Iterator +60 |-from typing import KeysView + 60 |+from collections.abc import KeysView +61 61 | from typing import Mapping +62 62 | from typing import MappingView +63 63 | from typing import MutableMapping + +UP035.py:61:1: UP035 [*] Import from `collections.abc` instead: `Mapping` + | +59 | from typing import Iterator +60 | from typing import KeysView +61 | from typing import Mapping + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +62 | from typing import MappingView +63 | from typing import MutableMapping + | + = help: Import from `collections.abc` + +ℹ Suggested fix +58 58 | from typing import Iterable +59 59 | from typing import Iterator +60 60 | from typing import KeysView +61 |-from typing import Mapping + 61 |+from collections.abc import Mapping +62 62 | from typing import MappingView +63 63 | from typing import MutableMapping +64 64 | from typing import MutableSequence + +UP035.py:62:1: UP035 [*] Import from `collections.abc` instead: `MappingView` + | +60 | from typing import KeysView +61 | from typing import Mapping +62 | from typing import MappingView + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +63 | from typing import MutableMapping +64 | from typing import MutableSequence + | + = help: Import from `collections.abc` + +ℹ Suggested fix +59 59 | from typing import Iterator +60 60 | from typing import KeysView +61 61 | from typing import Mapping +62 |-from typing import MappingView + 62 |+from collections.abc import MappingView +63 63 | from typing import MutableMapping +64 64 | from typing import MutableSequence +65 65 | from typing import MutableSet + +UP035.py:63:1: UP035 [*] Import from `collections.abc` instead: `MutableMapping` + | +61 | from typing import Mapping +62 | from typing import MappingView +63 | from typing import MutableMapping + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +64 | from typing import MutableSequence +65 | from typing import MutableSet + | + = help: Import from `collections.abc` + +ℹ Suggested fix +60 60 | from typing import KeysView +61 61 | from typing import Mapping +62 62 | from typing import MappingView +63 |-from typing import MutableMapping + 63 |+from collections.abc import MutableMapping +64 64 | from typing import MutableSequence +65 65 | from typing import MutableSet +66 66 | from typing import Sequence + +UP035.py:64:1: UP035 [*] Import from `collections.abc` instead: `MutableSequence` + | +62 | from typing import MappingView +63 | from typing import MutableMapping +64 | from typing import MutableSequence + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +65 | from typing import MutableSet +66 | from typing import Sequence + | + = help: Import from `collections.abc` + +ℹ Suggested fix +61 61 | from typing import Mapping +62 62 | from typing import MappingView +63 63 | from typing import MutableMapping +64 |-from typing import MutableSequence + 64 |+from collections.abc import MutableSequence +65 65 | from typing import MutableSet +66 66 | from typing import Sequence +67 67 | from typing import Sized + +UP035.py:65:1: UP035 [*] Import from `collections.abc` instead: `MutableSet` + | +63 | from typing import MutableMapping +64 | from typing import MutableSequence +65 | from typing import MutableSet + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +66 | from typing import Sequence +67 | from typing import Sized + | + = help: Import from `collections.abc` + +ℹ Suggested fix +62 62 | from typing import MappingView +63 63 | from typing import MutableMapping +64 64 | from typing import MutableSequence +65 |-from typing import MutableSet + 65 |+from collections.abc import MutableSet +66 66 | from typing import Sequence +67 67 | from typing import Sized +68 68 | from typing import ValuesView + +UP035.py:66:1: UP035 [*] Import from `collections.abc` instead: `Sequence` + | +64 | from typing import MutableSequence +65 | from typing import MutableSet +66 | from typing import Sequence + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +67 | from typing import Sized +68 | from typing import ValuesView + | + = help: Import from `collections.abc` + +ℹ Suggested fix +63 63 | from typing import MutableMapping +64 64 | from typing import MutableSequence +65 65 | from typing import MutableSet +66 |-from typing import Sequence + 66 |+from collections.abc import Sequence +67 67 | from typing import Sized +68 68 | from typing import ValuesView +69 69 | from typing import Awaitable + +UP035.py:67:1: UP035 [*] Import from `collections.abc` instead: `Sized` + | +65 | from typing import MutableSet +66 | from typing import Sequence +67 | from typing import Sized + | ^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +68 | from typing import ValuesView +69 | from typing import Awaitable + | + = help: Import from `collections.abc` + +ℹ Suggested fix +64 64 | from typing import MutableSequence +65 65 | from typing import MutableSet +66 66 | from typing import Sequence +67 |-from typing import Sized + 67 |+from collections.abc import Sized +68 68 | from typing import ValuesView +69 69 | from typing import Awaitable +70 70 | from typing import AsyncIterator + +UP035.py:68:1: UP035 [*] Import from `collections.abc` instead: `ValuesView` + | +66 | from typing import Sequence +67 | from typing import Sized +68 | from typing import ValuesView + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +69 | from typing import Awaitable +70 | from typing import AsyncIterator + | + = help: Import from `collections.abc` + +ℹ Suggested fix +65 65 | from typing import MutableSet +66 66 | from typing import Sequence +67 67 | from typing import Sized +68 |-from typing import ValuesView + 68 |+from collections.abc import ValuesView +69 69 | from typing import Awaitable +70 70 | from typing import AsyncIterator +71 71 | from typing import AsyncIterable + +UP035.py:69:1: UP035 [*] Import from `collections.abc` instead: `Awaitable` + | +67 | from typing import Sized +68 | from typing import ValuesView +69 | from typing import Awaitable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +70 | from typing import AsyncIterator +71 | from typing import AsyncIterable + | + = help: Import from `collections.abc` + +ℹ Suggested fix +66 66 | from typing import Sequence +67 67 | from typing import Sized +68 68 | from typing import ValuesView +69 |-from typing import Awaitable + 69 |+from collections.abc import Awaitable +70 70 | from typing import AsyncIterator +71 71 | from typing import AsyncIterable +72 72 | from typing import Coroutine + +UP035.py:70:1: UP035 [*] Import from `collections.abc` instead: `AsyncIterator` + | +68 | from typing import ValuesView +69 | from typing import Awaitable +70 | from typing import AsyncIterator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +71 | from typing import AsyncIterable +72 | from typing import Coroutine + | + = help: Import from `collections.abc` + +ℹ Suggested fix +67 67 | from typing import Sized +68 68 | from typing import ValuesView +69 69 | from typing import Awaitable +70 |-from typing import AsyncIterator + 70 |+from collections.abc import AsyncIterator +71 71 | from typing import AsyncIterable +72 72 | from typing import Coroutine +73 73 | from typing import Collection + +UP035.py:71:1: UP035 [*] Import from `collections.abc` instead: `AsyncIterable` + | +69 | from typing import Awaitable +70 | from typing import AsyncIterator +71 | from typing import AsyncIterable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +72 | from typing import Coroutine +73 | from typing import Collection + | + = help: Import from `collections.abc` + +ℹ Suggested fix +68 68 | from typing import ValuesView +69 69 | from typing import Awaitable +70 70 | from typing import AsyncIterator +71 |-from typing import AsyncIterable + 71 |+from collections.abc import AsyncIterable +72 72 | from typing import Coroutine +73 73 | from typing import Collection +74 74 | from typing import AsyncGenerator + +UP035.py:72:1: UP035 [*] Import from `collections.abc` instead: `Coroutine` + | +70 | from typing import AsyncIterator +71 | from typing import AsyncIterable +72 | from typing import Coroutine + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +73 | from typing import Collection +74 | from typing import AsyncGenerator + | + = help: Import from `collections.abc` + +ℹ Suggested fix +69 69 | from typing import Awaitable +70 70 | from typing import AsyncIterator +71 71 | from typing import AsyncIterable +72 |-from typing import Coroutine + 72 |+from collections.abc import Coroutine +73 73 | from typing import Collection +74 74 | from typing import AsyncGenerator +75 75 | from typing import Reversible + +UP035.py:73:1: UP035 [*] Import from `collections.abc` instead: `Collection` + | +71 | from typing import AsyncIterable +72 | from typing import Coroutine +73 | from typing import Collection + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +74 | from typing import AsyncGenerator +75 | from typing import Reversible + | + = help: Import from `collections.abc` + +ℹ Suggested fix +70 70 | from typing import AsyncIterator +71 71 | from typing import AsyncIterable +72 72 | from typing import Coroutine +73 |-from typing import Collection + 73 |+from collections.abc import Collection +74 74 | from typing import AsyncGenerator +75 75 | from typing import Reversible +76 76 | from typing import Generator + +UP035.py:74:1: UP035 [*] Import from `collections.abc` instead: `AsyncGenerator` + | +72 | from typing import Coroutine +73 | from typing import Collection +74 | from typing import AsyncGenerator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +75 | from typing import Reversible +76 | from typing import Generator + | + = help: Import from `collections.abc` + +ℹ Suggested fix +71 71 | from typing import AsyncIterable +72 72 | from typing import Coroutine +73 73 | from typing import Collection +74 |-from typing import AsyncGenerator + 74 |+from collections.abc import AsyncGenerator +75 75 | from typing import Reversible +76 76 | from typing import Generator +77 77 | + +UP035.py:75:1: UP035 [*] Import from `collections.abc` instead: `Reversible` + | +73 | from typing import Collection +74 | from typing import AsyncGenerator +75 | from typing import Reversible + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +76 | from typing import Generator + | + = help: Import from `collections.abc` + +ℹ Suggested fix +72 72 | from typing import Coroutine +73 73 | from typing import Collection +74 74 | from typing import AsyncGenerator +75 |-from typing import Reversible + 75 |+from collections.abc import Reversible +76 76 | from typing import Generator +77 77 | +78 78 | # OK + +UP035.py:76:1: UP035 [*] Import from `collections.abc` instead: `Generator` + | +74 | from typing import AsyncGenerator +75 | from typing import Reversible +76 | from typing import Generator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +77 | +78 | # OK + | + = help: Import from `collections.abc` + +ℹ Suggested fix +73 73 | from typing import Collection +74 74 | from typing import AsyncGenerator +75 75 | from typing import Reversible +76 |-from typing import Generator + 76 |+from collections.abc import Generator +77 77 | +78 78 | # OK +79 79 | from a import b + +UP035.py:88:1: UP035 [*] Import from `typing` instead: `dataclass_transform` + | +87 | # Ok: `typing_extensions` supports `frozen_default` (backported from 3.12). +88 | from typing_extensions import dataclass_transform + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 + | + = help: Import from `typing` + +ℹ Suggested fix +85 85 | from typing_extensions import NamedTuple +86 86 | +87 87 | # Ok: `typing_extensions` supports `frozen_default` (backported from 3.12). +88 |-from typing_extensions import dataclass_transform + 88 |+from typing import dataclass_transform + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP040.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP040.py.snap new file mode 100644 index 0000000000000..33d0e3b165f09 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP040.py.snap @@ -0,0 +1,232 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- +UP040.py:5:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +4 | # UP040 +5 | x: typing.TypeAlias = int + | ^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +6 | x: TypeAlias = int + | + = help: Use the `type` keyword + +ℹ Fix +2 2 | from typing import TypeAlias +3 3 | +4 4 | # UP040 +5 |-x: typing.TypeAlias = int + 5 |+type x = int +6 6 | x: TypeAlias = int +7 7 | +8 8 | # UP040 simple generic + +UP040.py:6:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +4 | # UP040 +5 | x: typing.TypeAlias = int +6 | x: TypeAlias = int + | ^^^^^^^^^^^^^^^^^^ UP040 +7 | +8 | # UP040 simple generic + | + = help: Use the `type` keyword + +ℹ Fix +3 3 | +4 4 | # UP040 +5 5 | x: typing.TypeAlias = int +6 |-x: TypeAlias = int + 6 |+type x = int +7 7 | +8 8 | # UP040 simple generic +9 9 | T = typing.TypeVar["T"] + +UP040.py:10:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | + 8 | # UP040 simple generic + 9 | T = typing.TypeVar["T"] +10 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +11 | +12 | # UP040 call style generic + | + = help: Use the `type` keyword + +ℹ Fix +7 7 | +8 8 | # UP040 simple generic +9 9 | T = typing.TypeVar["T"] +10 |-x: typing.TypeAlias = list[T] + 10 |+type x[T] = list[T] +11 11 | +12 12 | # UP040 call style generic +13 13 | T = typing.TypeVar("T") + +UP040.py:14:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +12 | # UP040 call style generic +13 | T = typing.TypeVar("T") +14 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +15 | +16 | # UP040 bounded generic (todo) + | + = help: Use the `type` keyword + +ℹ Fix +11 11 | +12 12 | # UP040 call style generic +13 13 | T = typing.TypeVar("T") +14 |-x: typing.TypeAlias = list[T] + 14 |+type x[T] = list[T] +15 15 | +16 16 | # UP040 bounded generic (todo) +17 17 | T = typing.TypeVar("T", bound=int) + +UP040.py:18:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +16 | # UP040 bounded generic (todo) +17 | T = typing.TypeVar("T", bound=int) +18 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +19 | +20 | T = typing.TypeVar("T", int, str) + | + = help: Use the `type` keyword + +ℹ Fix +15 15 | +16 16 | # UP040 bounded generic (todo) +17 17 | T = typing.TypeVar("T", bound=int) +18 |-x: typing.TypeAlias = list[T] + 18 |+type x = list[T] +19 19 | +20 20 | T = typing.TypeVar("T", int, str) +21 21 | x: typing.TypeAlias = list[T] + +UP040.py:21:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +20 | T = typing.TypeVar("T", int, str) +21 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +22 | +23 | # UP040 contravariant generic (todo) + | + = help: Use the `type` keyword + +ℹ Fix +18 18 | x: typing.TypeAlias = list[T] +19 19 | +20 20 | T = typing.TypeVar("T", int, str) +21 |-x: typing.TypeAlias = list[T] + 21 |+type x = list[T] +22 22 | +23 23 | # UP040 contravariant generic (todo) +24 24 | T = typing.TypeVar("T", contravariant=True) + +UP040.py:25:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +23 | # UP040 contravariant generic (todo) +24 | T = typing.TypeVar("T", contravariant=True) +25 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +26 | +27 | # UP040 covariant generic (todo) + | + = help: Use the `type` keyword + +ℹ Fix +22 22 | +23 23 | # UP040 contravariant generic (todo) +24 24 | T = typing.TypeVar("T", contravariant=True) +25 |-x: typing.TypeAlias = list[T] + 25 |+type x = list[T] +26 26 | +27 27 | # UP040 covariant generic (todo) +28 28 | T = typing.TypeVar("T", covariant=True) + +UP040.py:29:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +27 | # UP040 covariant generic (todo) +28 | T = typing.TypeVar("T", covariant=True) +29 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +30 | +31 | # UP040 in class scope + | + = help: Use the `type` keyword + +ℹ Fix +26 26 | +27 27 | # UP040 covariant generic (todo) +28 28 | T = typing.TypeVar("T", covariant=True) +29 |-x: typing.TypeAlias = list[T] + 29 |+type x = list[T] +30 30 | +31 31 | # UP040 in class scope +32 32 | T = typing.TypeVar["T"] + +UP040.py:35:5: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +33 | class Foo: +34 | # reference to global variable +35 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +36 | +37 | # reference to class variable + | + = help: Use the `type` keyword + +ℹ Fix +32 32 | T = typing.TypeVar["T"] +33 33 | class Foo: +34 34 | # reference to global variable +35 |- x: typing.TypeAlias = list[T] + 35 |+ type x[T] = list[T] +36 36 | +37 37 | # reference to class variable +38 38 | TCLS = typing.TypeVar["TCLS"] + +UP040.py:39:5: UP040 [*] Type alias `y` uses `TypeAlias` annotation instead of the `type` keyword + | +37 | # reference to class variable +38 | TCLS = typing.TypeVar["TCLS"] +39 | y: typing.TypeAlias = list[TCLS] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +40 | +41 | # UP040 wont add generics in fix + | + = help: Use the `type` keyword + +ℹ Fix +36 36 | +37 37 | # reference to class variable +38 38 | TCLS = typing.TypeVar["TCLS"] +39 |- y: typing.TypeAlias = list[TCLS] + 39 |+ type y[TCLS] = list[TCLS] +40 40 | +41 41 | # UP040 wont add generics in fix +42 42 | T = typing.TypeVar(*args) + +UP040.py:43:1: UP040 [*] Type alias `x` uses `TypeAlias` annotation instead of the `type` keyword + | +41 | # UP040 wont add generics in fix +42 | T = typing.TypeVar(*args) +43 | x: typing.TypeAlias = list[T] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP040 +44 | +45 | # OK + | + = help: Use the `type` keyword + +ℹ Fix +40 40 | +41 41 | # UP040 wont add generics in fix +42 42 | T = typing.TypeVar(*args) +43 |-x: typing.TypeAlias = list[T] + 43 |+type x = list[T] +44 44 | +45 45 | # OK +46 46 | x: TypeAlias + + diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap new file mode 100644 index 0000000000000..870ad3bf5d625 --- /dev/null +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__non_pep695_type_alias_not_applied_py311.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/pyupgrade/mod.rs +--- + diff --git a/crates/ruff/src/rules/ruff/mod.rs b/crates/ruff/src/rules/ruff/mod.rs index 42350547abd15..79028c9b5b235 100644 --- a/crates/ruff/src/rules/ruff/mod.rs +++ b/crates/ruff/src/rules/ruff/mod.rs @@ -40,6 +40,7 @@ mod tests { feature = "unreachable-code", test_case(Rule::UnreachableCode, Path::new("RUF014.py")) )] + #[test_case(Rule::QuadraticListSummation, Path::new("RUF017.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( @@ -60,10 +61,8 @@ mod tests { ); let diagnostics = test_path( Path::new("ruff").join(path).as_path(), - &settings::Settings { - target_version: PythonVersion::Py39, - ..settings::Settings::for_rule(Rule::ImplicitOptional) - }, + &settings::Settings::for_rule(Rule::ImplicitOptional) + .with_target_version(PythonVersion::Py39), )?; assert_messages!(snapshot, diagnostics); Ok(()) @@ -156,6 +155,31 @@ mod tests { Ok(()) } + #[test] + fn ruf100_4() -> Result<()> { + let diagnostics = test_path( + Path::new("ruff/RUF100_4.py"), + &settings::Settings::for_rules(vec![Rule::UnusedNOQA, Rule::UnusedImport]), + )?; + assert_messages!(diagnostics); + Ok(()) + } + + #[test] + fn ruf100_5() -> Result<()> { + let diagnostics = test_path( + Path::new("ruff/RUF100_5.py"), + &settings::Settings { + ..settings::Settings::for_rules(vec![ + Rule::UnusedNOQA, + Rule::LineTooLong, + Rule::CommentedOutCode, + ]) + }, + )?; + assert_messages!(diagnostics); + Ok(()) + } #[test] fn flake8_noqa() -> Result<()> { let diagnostics = test_path( diff --git a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs index a2156f8e11a47..604b81a88c2d0 100644 --- a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs +++ b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs @@ -1,9 +1,9 @@ -use ruff_python_ast::{self as ast, Expr, ExprContext, Operator, Ranged}; -use ruff_text_size::TextRange; - use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, ExprContext, Operator, Ranged}; +use ruff_text_size::TextRange; +use crate::autofix::snippet::SourceCodeSnippet; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -39,7 +39,7 @@ use crate::registry::AsRule; /// - [Python documentation: Sequence Types — `list`, `tuple`, `range`](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range) #[violation] pub struct CollectionLiteralConcatenation { - expr: String, + expression: SourceCodeSnippet, } impl Violation for CollectionLiteralConcatenation { @@ -47,13 +47,21 @@ impl Violation for CollectionLiteralConcatenation { #[derive_message_formats] fn message(&self) -> String { - let CollectionLiteralConcatenation { expr } = self; - format!("Consider `{expr}` instead of concatenation") + let CollectionLiteralConcatenation { expression } = self; + if let Some(expression) = expression.full_display() { + format!("Consider `{expression}` instead of concatenation") + } else { + format!("Consider iterable unpacking instead of concatenation") + } } fn autofix_title(&self) -> Option { - let CollectionLiteralConcatenation { expr } = self; - Some(format!("Replace with `{expr}`")) + let CollectionLiteralConcatenation { expression } = self; + if let Some(expression) = expression.full_display() { + Some(format!("Replace with `{expression}`")) + } else { + Some(format!("Replace with iterable unpacking")) + } } } @@ -166,7 +174,7 @@ fn concatenate_expressions(expr: &Expr) -> Option<(Expr, Type)> { pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Expr) { // If the expression is already a child of an addition, we'll have analyzed it already. if matches!( - checker.semantic().expr_parent(), + checker.semantic().current_expression_parent(), Some(Expr::BinOp(ast::ExprBinOp { op: Operator::Add, .. @@ -186,7 +194,7 @@ pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Exp }; let mut diagnostic = Diagnostic::new( CollectionLiteralConcatenation { - expr: contents.clone(), + expression: SourceCodeSnippet::new(contents.clone()), }, expr.range(), ); diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index ef4b22afd321f..f8957b82b244f 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -2,16 +2,15 @@ use anyhow::{bail, Result}; use libcst_native::{ ConcatenatedString, Expression, FormattedStringContent, FormattedStringExpression, }; -use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged}; use ruff_python_codegen::Stylist; use ruff_source_file::Locator; -use crate::autofix::codemods::CodegenStylist; use crate::checkers::ast::Checker; -use crate::cst::matchers::{match_call_mut, match_expression, match_name}; +use crate::cst::matchers::{match_call_mut, match_name, transform_expression}; use crate::registry::AsRule; /// ## What it does @@ -80,8 +79,12 @@ pub(crate) fn explicit_f_string_type_conversion( let Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: + Arguments { + args, + keywords, + range: _, + }, .. }) = value.as_ref() else { @@ -135,36 +138,28 @@ fn convert_call_to_conversion_flag( locator: &Locator, stylist: &Stylist, ) -> Result { - // Parenthesize the expression, to support implicit concatenation. - let range = expr.range(); - let content = locator.slice(range); - let parenthesized_content = format!("({content})"); - let mut expression = match_expression(&parenthesized_content)?; - - // Replace the formatted call expression at `index` with a conversion flag. - let formatted_string_expression = match_part(index, &mut expression)?; - let call = match_call_mut(&mut formatted_string_expression.expression)?; - let name = match_name(&call.func)?; - match name.value { - "str" => { - formatted_string_expression.conversion = Some("s"); - } - "repr" => { - formatted_string_expression.conversion = Some("r"); - } - "ascii" => { - formatted_string_expression.conversion = Some("a"); + let source_code = locator.slice(expr.range()); + transform_expression(source_code, stylist, |mut expression| { + // Replace the formatted call expression at `index` with a conversion flag. + let formatted_string_expression = match_part(index, &mut expression)?; + let call = match_call_mut(&mut formatted_string_expression.expression)?; + let name = match_name(&call.func)?; + match name.value { + "str" => { + formatted_string_expression.conversion = Some("s"); + } + "repr" => { + formatted_string_expression.conversion = Some("r"); + } + "ascii" => { + formatted_string_expression.conversion = Some("a"); + } + _ => bail!("Unexpected function call: `{:?}`", name.value), } - _ => bail!("Unexpected function call: `{:?}`", name.value), - } - formatted_string_expression.expression = call.args[0].value.clone(); - - // Remove the parentheses (first and last characters). - let mut content = expression.codegen_stylist(stylist); - content.remove(0); - content.pop(); - - Ok(Fix::automatic(Edit::range_replacement(content, range))) + formatted_string_expression.expression = call.args[0].value.clone(); + Ok(expression) + }) + .map(|output| Fix::automatic(Edit::range_replacement(output, expr.range()))) } /// Return the [`FormattedStringContent`] at the given index in an f-string or implicit diff --git a/crates/ruff/src/rules/ruff/rules/helpers.rs b/crates/ruff/src/rules/ruff/rules/helpers.rs index ff7ff7c2c85c5..8ccb070376904 100644 --- a/crates/ruff/src/rules/ruff/rules/helpers.rs +++ b/crates/ruff/src/rules/ruff/rules/helpers.rs @@ -1,6 +1,6 @@ -use ruff_python_ast::{self as ast, Expr}; +use ruff_python_ast::{self as ast, Arguments, Expr}; -use ruff_python_ast::helpers::map_callable; +use ruff_python_ast::helpers::{map_callable, map_subscript}; use ruff_python_semantic::{BindingKind, SemanticModel}; /// Return `true` if the given [`Expr`] is a special class attribute, like `__slots__`. @@ -21,25 +21,23 @@ pub(super) fn is_special_attribute(value: &Expr) -> bool { /// Returns `true` if the given [`Expr`] is a `dataclasses.field` call. pub(super) fn is_dataclass_field(func: &Expr, semantic: &SemanticModel) -> bool { - semantic.resolve_call_path(func).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["dataclasses", "field"]) - }) + semantic + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["dataclasses", "field"])) } /// Returns `true` if the given [`Expr`] is a `typing.ClassVar` annotation. pub(super) fn is_class_var_annotation(annotation: &Expr, semantic: &SemanticModel) -> bool { - let Expr::Subscript(ast::ExprSubscript { value, .. }) = &annotation else { - return false; - }; - semantic.match_typing_expr(value, "ClassVar") + // ClassVar can be used either with a subscript `ClassVar[...]` or without (the type is + // inferred). + semantic.match_typing_expr(map_subscript(annotation), "ClassVar") } /// Returns `true` if the given [`Expr`] is a `typing.Final` annotation. pub(super) fn is_final_annotation(annotation: &Expr, semantic: &SemanticModel) -> bool { - let Expr::Subscript(ast::ExprSubscript { value, .. }) = &annotation else { - return false; - }; - semantic.match_typing_expr(value, "Final") + // Final can be used either with a subscript `Final[...]` or without (the type is + // inferred). + semantic.match_typing_expr(map_subscript(annotation), "Final") } /// Returns `true` if the given class is a dataclass. @@ -47,16 +45,18 @@ pub(super) fn is_dataclass(class_def: &ast::StmtClassDef, semantic: &SemanticMod class_def.decorator_list.iter().any(|decorator| { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["dataclasses", "dataclass"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["dataclasses", "dataclass"])) }) } /// Returns `true` if the given class is a Pydantic `BaseModel` or `BaseSettings` subclass. pub(super) fn is_pydantic_model(class_def: &ast::StmtClassDef, semantic: &SemanticModel) -> bool { - class_def.bases.iter().any(|expr| { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + let Some(Arguments { args: bases, .. }) = class_def.arguments.as_deref() else { + return false; + }; + + bases.iter().any(|expr| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { matches!( call_path.as_slice(), ["pydantic", "BaseModel" | "BaseSettings"] @@ -70,16 +70,16 @@ pub(super) fn is_pydantic_model(class_def: &ast::StmtClassDef, semantic: &Semant /// /// See: pub(super) fn is_descriptor_class(func: &Expr, semantic: &SemanticModel) -> bool { - semantic.lookup_attribute(func).map_or(false, |id| { + semantic.lookup_attribute(func).is_some_and(|id| { let BindingKind::ClassDefinition(scope_id) = semantic.binding(id).kind else { return false; }; // Look for `__get__`, `__set__`, and `__delete__` methods. ["__get__", "__set__", "__delete__"].iter().any(|method| { - semantic.scopes[scope_id].get(method).map_or(false, |id| { - semantic.binding(id).kind.is_function_definition() - }) + semantic.scopes[scope_id] + .get(method) + .is_some_and(|id| semantic.binding(id).kind.is_function_definition()) }) }) } diff --git a/crates/ruff/src/rules/ruff/rules/implicit_optional.rs b/crates/ruff/src/rules/ruff/rules/implicit_optional.rs index 0ceca1982d382..fbda0f5ede2ae 100644 --- a/crates/ruff/src/rules/ruff/rules/implicit_optional.rs +++ b/crates/ruff/src/rules/ruff/rules/implicit_optional.rs @@ -1,7 +1,9 @@ use std::fmt; use anyhow::Result; -use ruff_python_ast::{self as ast, ArgWithDefault, Arguments, Constant, Expr, Operator, Ranged}; +use ruff_python_ast::{ + self as ast, Constant, Expr, Operator, ParameterWithDefault, Parameters, Ranged, +}; use ruff_text_size::TextRange; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -88,7 +90,8 @@ impl Violation for ImplicitOptional { } fn autofix_title(&self) -> Option { - Some(format!("Convert to `{}`", self.conversion_type)) + let ImplicitOptional { conversion_type } = self; + Some(format!("Convert to `{conversion_type}`")) } } @@ -165,22 +168,22 @@ fn generate_fix(checker: &Checker, conversion_type: ConversionType, expr: &Expr) } /// RUF013 -pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) { - for ArgWithDefault { - def, +pub(crate) fn implicit_optional(checker: &mut Checker, parameters: &Parameters) { + for ParameterWithDefault { + parameter, default, range: _, - } in arguments + } in parameters .posonlyargs .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) { let Some(default) = default else { continue }; if !is_const_none(default) { continue; } - let Some(annotation) = &def.annotation else { + let Some(annotation) = ¶meter.annotation else { continue; }; diff --git a/crates/ruff/src/rules/ruff/rules/invalid_index_type.rs b/crates/ruff/src/rules/ruff/rules/invalid_index_type.rs index 87b30117aba14..74be4ac75bec7 100644 --- a/crates/ruff/src/rules/ruff/rules/invalid_index_type.rs +++ b/crates/ruff/src/rules/ruff/rules/invalid_index_type.rs @@ -63,7 +63,7 @@ pub(crate) fn invalid_index_type(checker: &mut Checker, expr: &ExprSubscript) { Expr::List(_) | Expr::ListComp(_) | Expr::Tuple(_) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::Constant(ExprConstant { value: Constant::Str(_) | Constant::Bytes(_), .. @@ -156,7 +156,7 @@ pub(crate) fn invalid_index_type(checker: &mut Checker, expr: &ExprSubscript) { #[derive(Debug)] enum CheckableExprType<'a> { Constant(&'a Constant), - JoinedStr, + FString, List, ListComp, SetComp, @@ -171,7 +171,7 @@ impl fmt::Display for CheckableExprType<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::Constant(constant) => f.write_str(constant_type_name(constant)), - Self::JoinedStr => f.write_str("str"), + Self::FString => f.write_str("str"), Self::List => f.write_str("list"), Self::SetComp => f.write_str("set comprehension"), Self::ListComp => f.write_str("list comprehension"), @@ -188,7 +188,7 @@ impl<'a> CheckableExprType<'a> { fn try_from(expr: &'a Expr) -> Option { match expr { Expr::Constant(ExprConstant { value, .. }) => Some(Self::Constant(value)), - Expr::JoinedStr(_) => Some(Self::JoinedStr), + Expr::FString(_) => Some(Self::FString), Expr::List(_) => Some(Self::List), Expr::ListComp(_) => Some(Self::ListComp), Expr::SetComp(_) => Some(Self::SetComp), diff --git a/crates/ruff/src/rules/ruff/rules/invalid_pyproject_toml.rs b/crates/ruff/src/rules/ruff/rules/invalid_pyproject_toml.rs index 6410cb526dc85..fc5482b9c24e2 100644 --- a/crates/ruff/src/rules/ruff/rules/invalid_pyproject_toml.rs +++ b/crates/ruff/src/rules/ruff/rules/invalid_pyproject_toml.rs @@ -40,6 +40,7 @@ impl Violation for InvalidPyprojectToml { #[derive_message_formats] fn message(&self) -> String { - format!("Failed to parse pyproject.toml: {}", self.message) + let InvalidPyprojectToml { message } = self; + format!("Failed to parse pyproject.toml: {message}") } } diff --git a/crates/ruff/src/rules/ruff/rules/mod.rs b/crates/ruff/src/rules/ruff/rules/mod.rs index e4d39feefd825..8ffa324791c30 100644 --- a/crates/ruff/src/rules/ruff/rules/mod.rs +++ b/crates/ruff/src/rules/ruff/rules/mod.rs @@ -40,3 +40,6 @@ pub(crate) enum Context { Docstring, Comment, } +pub(crate) use quadratic_list_summation::*; + +mod quadratic_list_summation; diff --git a/crates/ruff/src/rules/ruff/rules/mutable_class_default.rs b/crates/ruff/src/rules/ruff/rules/mutable_class_default.rs index 11fbcd0374c17..d411a6fadb49b 100644 --- a/crates/ruff/src/rules/ruff/rules/mutable_class_default.rs +++ b/crates/ruff/src/rules/ruff/rules/mutable_class_default.rs @@ -60,7 +60,7 @@ pub(crate) fn mutable_class_default(checker: &mut Checker, class_def: &ast::Stmt && is_mutable_expr(value, checker.semantic()) && !is_class_var_annotation(annotation, checker.semantic()) && !is_final_annotation(annotation, checker.semantic()) - && !is_immutable_annotation(annotation, checker.semantic()) + && !is_immutable_annotation(annotation, checker.semantic(), &[]) && !is_dataclass(class_def, checker.semantic()) { // Avoid Pydantic models, which end up copying defaults on instance creation. diff --git a/crates/ruff/src/rules/ruff/rules/mutable_dataclass_default.rs b/crates/ruff/src/rules/ruff/rules/mutable_dataclass_default.rs index 24f2ff9f1e351..e916d6de18fde 100644 --- a/crates/ruff/src/rules/ruff/rules/mutable_dataclass_default.rs +++ b/crates/ruff/src/rules/ruff/rules/mutable_dataclass_default.rs @@ -76,7 +76,7 @@ pub(crate) fn mutable_dataclass_default(checker: &mut Checker, class_def: &ast:: { if is_mutable_expr(value, checker.semantic()) && !is_class_var_annotation(annotation, checker.semantic()) - && !is_immutable_annotation(annotation, checker.semantic()) + && !is_immutable_annotation(annotation, checker.semantic(), &[]) { checker .diagnostics diff --git a/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs b/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs new file mode 100644 index 0000000000000..427f1d052c6cd --- /dev/null +++ b/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs @@ -0,0 +1,133 @@ +use anyhow::Result; + +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Arguments, Expr, Ranged}; +use ruff_python_semantic::SemanticModel; + +use crate::importer::ImportRequest; +use crate::{checkers::ast::Checker, registry::Rule}; + +/// ## What it does +/// Checks for the use of `sum()` to flatten lists of lists, which has +/// quadratic complexity. +/// +/// ## Why is this bad? +/// The use of `sum()` to flatten lists of lists is quadratic in the number of +/// lists, as `sum()` creates a new list for each element in the summation. +/// +/// Instead, consider using another method of flattening lists to avoid +/// quadratic complexity. The following methods are all linear in the number of +/// lists: +/// +/// - `functools.reduce(operator.iconcat, lists, [])` +/// - `list(itertools.chain.from_iterable(lists)` +/// - `[item for sublist in lists for item in sublist]` +/// +/// ## Example +/// ```python +/// lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] +/// joined = sum(lists, []) +/// ``` +/// +/// Use instead: +/// ```python +/// import functools +/// import operator +/// +/// +/// lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] +/// functools.reduce(operator.iconcat, lists, []) +/// ``` +/// +/// ## References +/// - [_How Not to Flatten a List of Lists in Python_](https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python) +/// - [_How do I make a flat list out of a list of lists?_](https://stackoverflow.com/questions/952914/how-do-i-make-a-flat-list-out-of-a-list-of-lists/953097#953097) +#[violation] +pub struct QuadraticListSummation; + +impl AlwaysAutofixableViolation for QuadraticListSummation { + #[derive_message_formats] + fn message(&self) -> String { + format!("Avoid quadratic list summation") + } + + fn autofix_title(&self) -> String { + format!("Replace with `functools.reduce`") + } +} + +/// RUF017 +pub(crate) fn quadratic_list_summation(checker: &mut Checker, call: &ast::ExprCall) { + let ast::ExprCall { + func, + arguments, + range, + } = call; + + if !func_is_builtin(func, "sum", checker.semantic()) { + return; + } + + if !start_is_empty_list(arguments, checker.semantic()) { + return; + }; + + let Some(iterable) = arguments.args.first() else { + return; + }; + + let mut diagnostic = Diagnostic::new(QuadraticListSummation, *range); + if checker.patch(Rule::QuadraticListSummation) { + diagnostic.try_set_fix(|| convert_to_reduce(iterable, call, checker)); + } + checker.diagnostics.push(diagnostic); +} + +/// Generate a [`Fix`] to convert a `sum()` call to a `functools.reduce()` call. +fn convert_to_reduce(iterable: &Expr, call: &ast::ExprCall, checker: &Checker) -> Result { + let (reduce_edit, reduce_binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("functools", "reduce"), + call.start(), + checker.semantic(), + )?; + + let (iadd_edit, iadd_binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("operator", "iadd"), + iterable.start(), + checker.semantic(), + )?; + + let iterable = checker.locator().slice(iterable.range()); + + Ok(Fix::suggested_edits( + Edit::range_replacement( + format!("{reduce_binding}({iadd_binding}, {iterable}, [])"), + call.range(), + ), + [reduce_edit, iadd_edit], + )) +} + +/// Check if a function is a builtin with a given name. +fn func_is_builtin(func: &Expr, name: &str, semantic: &SemanticModel) -> bool { + let Expr::Name(ast::ExprName { id, .. }) = func else { + return false; + }; + id == name && semantic.is_builtin(id) +} + +/// Returns `true` if the `start` argument to a `sum()` call is an empty list. +fn start_is_empty_list(arguments: &Arguments, semantic: &SemanticModel) -> bool { + let Some(start_arg) = arguments.find_argument("start", 1) else { + return false; + }; + + match start_arg { + Expr::Call(ast::ExprCall { + func, arguments, .. + }) => arguments.is_empty() && func_is_builtin(func, "list", semantic), + Expr::List(ast::ExprList { elts, ctx, .. }) => elts.is_empty() && ctx.is_load(), + _ => false, + } +} diff --git a/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs b/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs index 85ae2bb9dfedd..fcb3caa2c5e0e 100644 --- a/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs +++ b/crates/ruff/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs @@ -1,14 +1,14 @@ use std::borrow::Cow; use num_traits::Zero; -use unicode_width::UnicodeWidthStr; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::{self as ast, Comprehension, Constant, Expr, Ranged}; +use ruff_python_ast::{self as ast, Arguments, Comprehension, Constant, Expr, Ranged}; use ruff_python_semantic::SemanticModel; use ruff_text_size::{TextRange, TextSize}; +use crate::autofix::snippet::SourceCodeSnippet; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -47,35 +47,24 @@ use crate::registry::AsRule; /// - [Iterators and Iterables in Python: Run Efficient Iterations](https://realpython.com/python-iterators-iterables/#when-to-use-an-iterator-in-python) #[violation] pub(crate) struct UnnecessaryIterableAllocationForFirstElement { - iterable: String, + iterable: SourceCodeSnippet, } impl AlwaysAutofixableViolation for UnnecessaryIterableAllocationForFirstElement { #[derive_message_formats] fn message(&self) -> String { let UnnecessaryIterableAllocationForFirstElement { iterable } = self; - let iterable = Self::truncate(iterable); + let iterable = iterable.truncated_display(); format!("Prefer `next({iterable})` over single element slice") } fn autofix_title(&self) -> String { let UnnecessaryIterableAllocationForFirstElement { iterable } = self; - let iterable = Self::truncate(iterable); + let iterable = iterable.truncated_display(); format!("Replace with `next({iterable})`") } } -impl UnnecessaryIterableAllocationForFirstElement { - /// If the iterable is too long, or spans multiple lines, truncate it. - fn truncate(iterable: &str) -> &str { - if iterable.width() > 40 || iterable.contains(['\r', '\n']) { - "..." - } else { - iterable - } - } -} - /// RUF015 pub(crate) fn unnecessary_iterable_allocation_for_first_element( checker: &mut Checker, @@ -104,7 +93,7 @@ pub(crate) fn unnecessary_iterable_allocation_for_first_element( let mut diagnostic = Diagnostic::new( UnnecessaryIterableAllocationForFirstElement { - iterable: iterable.to_string(), + iterable: SourceCodeSnippet::new(iterable.to_string()), }, *range, ); @@ -149,9 +138,13 @@ struct IterationTarget { /// /// As a special-case, given `[x for x in y]`, returns the range of `y` (rather than the /// redundant comprehension). -fn match_iteration_target(expr: &Expr, model: &SemanticModel) -> Option { +fn match_iteration_target(expr: &Expr, semantic: &SemanticModel) -> Option { let result = match expr { - Expr::Call(ast::ExprCall { func, args, .. }) => { + Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) => { let ast::ExprName { id, .. } = func.as_name_expr()?; if !matches!(id.as_str(), "tuple" | "list") { @@ -162,7 +155,7 @@ fn match_iteration_target(expr: &Expr, model: &SemanticModel) -> Option( // For `break` statements we don't want to continue with the // loop, but instead with the statement after the loop (i.e. // not change anything). - !block.stmts.last().map_or(false, Stmt::is_break_stmt) + !block.stmts.last().is_some_and(Stmt::is_break_stmt) }, ); NextBlock::If { @@ -467,7 +467,6 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { let next = match stmt { // Statements that continue to the next statement after execution. Stmt::FunctionDef(_) - | Stmt::AsyncFunctionDef(_) | Stmt::Import(_) | Stmt::ImportFrom(_) | Stmt::ClassDef(_) @@ -535,12 +534,6 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { body, orelse, .. - }) - | Stmt::AsyncFor(StmtAsyncFor { - iter: condition, - body, - orelse, - .. }) => loop_block(self, Condition::Iterator(condition), body, orelse, after), Stmt::Try(StmtTry { body, @@ -548,13 +541,6 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { orelse, finalbody, .. - }) - | Stmt::TryStar(StmtTryStar { - body, - handlers, - orelse, - finalbody, - .. }) => { // TODO: handle `try` statements. The `try` control flow is very // complex, what blocks are and aren't taken and from which @@ -566,8 +552,7 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { let _ = (body, handlers, orelse, finalbody); // Silence unused code warnings. self.unconditional_next_block(after) } - Stmt::With(StmtWith { items, body, .. }) - | Stmt::AsyncWith(StmtAsyncWith { items, body, .. }) => { + Stmt::With(StmtWith { items, body, .. }) => { // TODO: handle `with` statements, see // . // I recommend to `try` statements first as `with` can desugar @@ -641,7 +626,7 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { | Expr::Compare(_) | Expr::Call(_) | Expr::FormattedValue(_) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::Constant(_) | Expr::Attribute(_) | Expr::Subscript(_) @@ -661,13 +646,13 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { | Expr::Await(_) | Expr::Yield(_) | Expr::YieldFrom(_) => self.unconditional_next_block(after), - Expr::LineMagic(_) => todo!(), + Expr::IpyEscapeCommand(_) => todo!(), } } // The tough branches are done, here is an easy one. Stmt::Return(_) => NextBlock::Terminate, Stmt::TypeAlias(_) => todo!(), - Stmt::LineMagic(_) => todo!(), + Stmt::IpyEscapeCommand(_) => todo!(), }; // Include any statements in the block that don't divert the control flow. @@ -889,7 +874,6 @@ fn needs_next_block(stmts: &[Stmt]) -> bool { Stmt::Return(_) | Stmt::Raise(_) => false, Stmt::If(stmt) => needs_next_block(&stmt.body) || stmt.elif_else_clauses.last().map_or(true, |clause| needs_next_block(&clause.body)), Stmt::FunctionDef(_) - | Stmt::AsyncFunctionDef(_) | Stmt::Import(_) | Stmt::ImportFrom(_) | Stmt::ClassDef(_) @@ -905,16 +889,13 @@ fn needs_next_block(stmts: &[Stmt]) -> bool { | Stmt::Break(_) | Stmt::Continue(_) | Stmt::For(_) - | Stmt::AsyncFor(_) | Stmt::While(_) | Stmt::With(_) - | Stmt::AsyncWith(_) | Stmt::Match(_) | Stmt::Try(_) - | Stmt::TryStar(_) | Stmt::Assert(_) => true, Stmt::TypeAlias(_) => todo!(), - Stmt::LineMagic(_) => todo!(), + Stmt::IpyEscapeCommand(_) => todo!(), } } @@ -923,7 +904,6 @@ fn needs_next_block(stmts: &[Stmt]) -> bool { fn is_control_flow_stmt(stmt: &Stmt) -> bool { match stmt { Stmt::FunctionDef(_) - | Stmt::AsyncFunctionDef(_) | Stmt::Import(_) | Stmt::ImportFrom(_) | Stmt::ClassDef(_) @@ -937,20 +917,17 @@ fn is_control_flow_stmt(stmt: &Stmt) -> bool { | Stmt::Pass(_) => false, Stmt::Return(_) | Stmt::For(_) - | Stmt::AsyncFor(_) | Stmt::While(_) | Stmt::If(_) | Stmt::With(_) - | Stmt::AsyncWith(_) | Stmt::Match(_) | Stmt::Raise(_) | Stmt::Try(_) - | Stmt::TryStar(_) | Stmt::Assert(_) | Stmt::Break(_) | Stmt::Continue(_) => true, Stmt::TypeAlias(_) => todo!(), - Stmt::LineMagic(_) => todo!(), + Stmt::IpyEscapeCommand(_) => todo!(), } } diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap index 5b874cb5b6f82..d2596ef929db6 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap @@ -187,7 +187,7 @@ RUF005.py:47:16: RUF005 [*] Consider `("we all feel", *Fun.words)` instead of co 49 49 | chain = ["a", "b", "c"] + eggs + list(("yes", "no", "pants") + zoob) 50 50 | -RUF005.py:49:9: RUF005 [*] Consider `["a", "b", "c", *eggs, *list(("yes", "no", "pants") + zoob)]` instead of concatenation +RUF005.py:49:9: RUF005 [*] Consider iterable unpacking instead of concatenation | 47 | astonishment = ("we all feel",) + Fun.words 48 | @@ -196,7 +196,7 @@ RUF005.py:49:9: RUF005 [*] Consider `["a", "b", "c", *eggs, *list(("yes", "no", 50 | 51 | baz = () + zoob | - = help: Replace with `["a", "b", "c", *eggs, *list(("yes", "no", "pants") + zoob)]` + = help: Replace with iterable unpacking ℹ Suggested fix 46 46 | excitement = ("we all think",) + Fun().yay() @@ -294,14 +294,14 @@ RUF005.py:56:15: RUF005 [*] Consider `[sys.executable, "-m", "pylint", *args, pa 58 58 | b = a + [2, 3] + [4] 59 59 | -RUF005.py:57:21: RUF005 [*] Consider `(sys.executable, "-m", "pylint", *args, path, path2)` instead of concatenation +RUF005.py:57:21: RUF005 [*] Consider iterable unpacking instead of concatenation | 56 | pylint_call = [sys.executable, "-m", "pylint"] + args + [path] 57 | pylint_call_tuple = (sys.executable, "-m", "pylint") + args + (path, path2) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF005 58 | b = a + [2, 3] + [4] | - = help: Replace with `(sys.executable, "-m", "pylint", *args, path, path2)` + = help: Replace with iterable unpacking ℹ Suggested fix 54 54 | ] diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF012_RUF012.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF012_RUF012.py.snap index 676e2a1a03805..81b1adfed7a2c 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF012_RUF012.py.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF012_RUF012.py.snap @@ -21,14 +21,14 @@ RUF012.py:11:26: RUF012 Mutable class attributes should be annotated with `typin 13 | final_variable: Final[list[int]] = [] | -RUF012.py:23:26: RUF012 Mutable class attributes should be annotated with `typing.ClassVar` +RUF012.py:25:26: RUF012 Mutable class attributes should be annotated with `typing.ClassVar` | -21 | mutable_default: list[int] = [] -22 | immutable_annotation: Sequence[int] = [] -23 | without_annotation = [] +23 | mutable_default: list[int] = [] +24 | immutable_annotation: Sequence[int] = [] +25 | without_annotation = [] | ^^ RUF012 -24 | perfectly_fine: list[int] = field(default_factory=list) -25 | class_variable: ClassVar[list[int]] = [] +26 | perfectly_fine: list[int] = field(default_factory=list) +27 | class_variable: ClassVar[list[int]] = [] | diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF017_RUF017.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF017_RUF017.py.snap new file mode 100644 index 0000000000000..b05d32ea23020 --- /dev/null +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF017_RUF017.py.snap @@ -0,0 +1,134 @@ +--- +source: crates/ruff/src/rules/ruff/mod.rs +--- +RUF017.py:5:1: RUF017 [*] Avoid quadratic list summation + | +4 | # RUF017 +5 | sum([x, y], start=[]) + | ^^^^^^^^^^^^^^^^^^^^^ RUF017 +6 | sum([x, y], []) +7 | sum([[1, 2, 3], [4, 5, 6]], start=[]) + | + = help: Replace with `functools.reduce` + +ℹ Suggested fix + 1 |+import functools + 2 |+import operator +1 3 | x = [1, 2, 3] +2 4 | y = [4, 5, 6] +3 5 | +4 6 | # RUF017 +5 |-sum([x, y], start=[]) + 7 |+functools.reduce(operator.iadd, [x, y], []) +6 8 | sum([x, y], []) +7 9 | sum([[1, 2, 3], [4, 5, 6]], start=[]) +8 10 | sum([[1, 2, 3], [4, 5, 6]], []) + +RUF017.py:6:1: RUF017 [*] Avoid quadratic list summation + | +4 | # RUF017 +5 | sum([x, y], start=[]) +6 | sum([x, y], []) + | ^^^^^^^^^^^^^^^ RUF017 +7 | sum([[1, 2, 3], [4, 5, 6]], start=[]) +8 | sum([[1, 2, 3], [4, 5, 6]], []) + | + = help: Replace with `functools.reduce` + +ℹ Suggested fix + 1 |+import functools + 2 |+import operator +1 3 | x = [1, 2, 3] +2 4 | y = [4, 5, 6] +3 5 | +4 6 | # RUF017 +5 7 | sum([x, y], start=[]) +6 |-sum([x, y], []) + 8 |+functools.reduce(operator.iadd, [x, y], []) +7 9 | sum([[1, 2, 3], [4, 5, 6]], start=[]) +8 10 | sum([[1, 2, 3], [4, 5, 6]], []) +9 11 | sum([[1, 2, 3], [4, 5, 6]], + +RUF017.py:7:1: RUF017 [*] Avoid quadratic list summation + | +5 | sum([x, y], start=[]) +6 | sum([x, y], []) +7 | sum([[1, 2, 3], [4, 5, 6]], start=[]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF017 +8 | sum([[1, 2, 3], [4, 5, 6]], []) +9 | sum([[1, 2, 3], [4, 5, 6]], + | + = help: Replace with `functools.reduce` + +ℹ Suggested fix + 1 |+import functools + 2 |+import operator +1 3 | x = [1, 2, 3] +2 4 | y = [4, 5, 6] +3 5 | +4 6 | # RUF017 +5 7 | sum([x, y], start=[]) +6 8 | sum([x, y], []) +7 |-sum([[1, 2, 3], [4, 5, 6]], start=[]) + 9 |+functools.reduce(operator.iadd, [[1, 2, 3], [4, 5, 6]], []) +8 10 | sum([[1, 2, 3], [4, 5, 6]], []) +9 11 | sum([[1, 2, 3], [4, 5, 6]], +10 12 | []) + +RUF017.py:8:1: RUF017 [*] Avoid quadratic list summation + | + 6 | sum([x, y], []) + 7 | sum([[1, 2, 3], [4, 5, 6]], start=[]) + 8 | sum([[1, 2, 3], [4, 5, 6]], []) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF017 + 9 | sum([[1, 2, 3], [4, 5, 6]], +10 | []) + | + = help: Replace with `functools.reduce` + +ℹ Suggested fix + 1 |+import functools + 2 |+import operator +1 3 | x = [1, 2, 3] +2 4 | y = [4, 5, 6] +3 5 | +-------------------------------------------------------------------------------- +5 7 | sum([x, y], start=[]) +6 8 | sum([x, y], []) +7 9 | sum([[1, 2, 3], [4, 5, 6]], start=[]) +8 |-sum([[1, 2, 3], [4, 5, 6]], []) + 10 |+functools.reduce(operator.iadd, [[1, 2, 3], [4, 5, 6]], []) +9 11 | sum([[1, 2, 3], [4, 5, 6]], +10 12 | []) +11 13 | + +RUF017.py:9:1: RUF017 [*] Avoid quadratic list summation + | + 7 | sum([[1, 2, 3], [4, 5, 6]], start=[]) + 8 | sum([[1, 2, 3], [4, 5, 6]], []) + 9 | / sum([[1, 2, 3], [4, 5, 6]], +10 | | []) + | |_______^ RUF017 +11 | +12 | # OK + | + = help: Replace with `functools.reduce` + +ℹ Suggested fix + 1 |+import functools + 2 |+import operator +1 3 | x = [1, 2, 3] +2 4 | y = [4, 5, 6] +3 5 | +-------------------------------------------------------------------------------- +6 8 | sum([x, y], []) +7 9 | sum([[1, 2, 3], [4, 5, 6]], start=[]) +8 10 | sum([[1, 2, 3], [4, 5, 6]], []) +9 |-sum([[1, 2, 3], [4, 5, 6]], +10 |- []) + 11 |+functools.reduce(operator.iadd, [[1, 2, 3], [4, 5, 6]], []) +11 12 | +12 13 | # OK +13 14 | sum([x, y]) + + diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_0.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_0.snap index 96a0369c89ce9..9694fbb82f21f 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_0.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_0.snap @@ -10,7 +10,7 @@ RUF100_0.py:9:12: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 6 6 | b = 2 # noqa: F841 7 7 | 8 8 | # Invalid @@ -30,7 +30,7 @@ RUF100_0.py:13:12: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 10 10 | print(c) 11 11 | 12 12 | # Invalid @@ -50,7 +50,7 @@ RUF100_0.py:16:12: RUF100 [*] Unused `noqa` directive (unused: `F841`, `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 13 13 | d = 1 # noqa: E501 14 14 | 15 15 | # Invalid @@ -70,7 +70,7 @@ RUF100_0.py:19:12: RUF100 [*] Unused `noqa` directive (unused: `F841`, `W191`; n | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 16 16 | d = 1 # noqa: F841, E501 17 17 | 18 18 | # Invalid (and unimplemented or not enabled) @@ -90,7 +90,7 @@ RUF100_0.py:22:12: RUF100 [*] Unused `noqa` directive (unused: `F841`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 19 19 | d = 1 # noqa: F841, W191, F821 20 20 | 21 21 | # Invalid (but external) @@ -111,7 +111,7 @@ RUF100_0.py:26:10: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 23 23 | 24 24 | # fmt: off 25 25 | # Invalid - no space before # @@ -148,7 +148,7 @@ RUF100_0.py:29:33: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 26 26 | d = 1# noqa: E501 27 27 | 28 28 | # Invalid - many spaces before # @@ -168,7 +168,7 @@ RUF100_0.py:55:6: RUF100 [*] Unused `noqa` directive (unused: `F841`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 52 52 | https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533 53 53 | 54 54 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. @@ -188,7 +188,7 @@ RUF100_0.py:63:6: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 60 60 | https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533 61 61 | 62 62 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor. @@ -208,7 +208,7 @@ RUF100_0.py:71:6: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 68 68 | https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533 69 69 | 70 70 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor. @@ -254,7 +254,7 @@ RUF100_0.py:90:92: RUF100 [*] Unused `noqa` directive (unused: `F401`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 87 87 | 88 88 | print(sys.path) 89 89 | diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_1.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_1.snap index ad606136dd610..10899059452d3 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_1.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_1.snap @@ -32,7 +32,7 @@ RUF100_1.py:52:20: RUF100 [*] Unused `noqa` directive (unused: `F401`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 49 49 | def f(): 50 50 | # This should ignore the error, but the inner noqa should be marked as unused. 51 51 | from typing import ( # noqa: F401 @@ -52,7 +52,7 @@ RUF100_1.py:59:20: RUF100 [*] Unused `noqa` directive (unused: `F401`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 56 56 | def f(): 57 57 | # This should ignore the error, but the inner noqa should be marked as unused. 58 58 | from typing import ( # noqa @@ -72,7 +72,7 @@ RUF100_1.py:66:16: RUF100 [*] Unused `noqa` directive (non-enabled: `F501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 63 63 | def f(): 64 64 | # This should ignore the error, but mark F501 as unused. 65 65 | from typing import ( # noqa: F401 @@ -93,7 +93,7 @@ RUF100_1.py:72:27: RUF100 [*] Unused `noqa` directive (non-enabled: `F501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 69 69 | 70 70 | def f(): 71 71 | # This should ignore the error, but mark F501 as unused. @@ -144,7 +144,7 @@ RUF100_1.py:89:55: RUF100 [*] Unused `noqa` directive (non-enabled: `F501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 86 86 | 87 87 | def f(): 88 88 | # This should mark F501 as unused. diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_2.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_2.snap index 7fd1341d115ae..38457da686658 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_2.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_2.snap @@ -8,7 +8,7 @@ RUF100_2.py:1:19: RUF100 [*] Unused `noqa` directive (unused: `F401`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 1 |-import itertools # noqa: F401 1 |+import itertools diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_3.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_3.snap index 4c56171cc0afb..01b8e0912aa3c 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_3.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_3.snap @@ -10,7 +10,7 @@ RUF100_3.py:1:1: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 1 |-# noqa 2 1 | # noqa # comment 3 2 | print() # noqa @@ -26,7 +26,7 @@ RUF100_3.py:2:1: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 1 1 | # noqa 2 |-# noqa # comment 2 |+# comment @@ -45,7 +45,7 @@ RUF100_3.py:3:10: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 1 1 | # noqa 2 2 | # noqa # comment 3 |-print() # noqa @@ -65,7 +65,7 @@ RUF100_3.py:4:10: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 1 1 | # noqa 2 2 | # noqa # comment 3 3 | print() # noqa @@ -86,7 +86,7 @@ RUF100_3.py:5:10: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 2 2 | # noqa # comment 3 3 | print() # noqa 4 4 | print() # noqa # comment @@ -107,7 +107,7 @@ RUF100_3.py:6:10: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 3 3 | print() # noqa 4 4 | print() # noqa # comment 5 5 | print() # noqa # comment @@ -128,7 +128,7 @@ RUF100_3.py:7:10: RUF100 [*] Unused blanket `noqa` directive | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 4 4 | print() # noqa # comment 5 5 | print() # noqa # comment 6 6 | print() # noqa comment @@ -149,7 +149,7 @@ RUF100_3.py:14:1: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 11 11 | print(a) # noqa comment 12 12 | print(a) # noqa comment 13 13 | @@ -168,7 +168,7 @@ RUF100_3.py:15:1: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 12 12 | print(a) # noqa comment 13 13 | 14 14 | # noqa: E501, F821 @@ -189,7 +189,7 @@ RUF100_3.py:16:10: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 13 13 | 14 14 | # noqa: E501, F821 15 15 | # noqa: E501, F821 # comment @@ -210,7 +210,7 @@ RUF100_3.py:17:10: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 14 14 | # noqa: E501, F821 15 15 | # noqa: E501, F821 # comment 16 16 | print() # noqa: E501, F821 @@ -231,7 +231,7 @@ RUF100_3.py:18:10: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 15 15 | # noqa: E501, F821 # comment 16 16 | print() # noqa: E501, F821 17 17 | print() # noqa: E501, F821 # comment @@ -252,7 +252,7 @@ RUF100_3.py:19:10: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 16 16 | print() # noqa: E501, F821 17 17 | print() # noqa: E501, F821 # comment 18 18 | print() # noqa: E501, F821 # comment @@ -273,7 +273,7 @@ RUF100_3.py:20:10: RUF100 [*] Unused `noqa` directive (unused: `E501`, `F821`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 17 17 | print() # noqa: E501, F821 # comment 18 18 | print() # noqa: E501, F821 # comment 19 19 | print() # noqa: E501, F821 comment @@ -294,7 +294,7 @@ RUF100_3.py:21:11: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 18 18 | print() # noqa: E501, F821 # comment 19 19 | print() # noqa: E501, F821 comment 20 20 | print() # noqa: E501, F821 comment @@ -315,7 +315,7 @@ RUF100_3.py:22:11: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 19 19 | print() # noqa: E501, F821 comment 20 20 | print() # noqa: E501, F821 comment 21 21 | print(a) # noqa: E501, F821 @@ -336,7 +336,7 @@ RUF100_3.py:23:11: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 20 20 | print() # noqa: E501, F821 comment 21 21 | print(a) # noqa: E501, F821 22 22 | print(a) # noqa: E501, F821 # comment @@ -355,7 +355,7 @@ RUF100_3.py:24:11: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 21 21 | print(a) # noqa: E501, F821 22 22 | print(a) # noqa: E501, F821 # comment 23 23 | print(a) # noqa: E501, F821 # comment @@ -372,7 +372,7 @@ RUF100_3.py:25:11: RUF100 [*] Unused `noqa` directive (unused: `E501`) | = help: Remove unused `noqa` directive -ℹ Suggested fix +ℹ Fix 22 22 | print(a) # noqa: E501, F821 # comment 23 23 | print(a) # noqa: E501, F821 # comment 24 24 | print(a) # noqa: E501, F821 comment diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_4.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_4.snap new file mode 100644 index 0000000000000..e51f71f81152a --- /dev/null +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_4.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/ruff/mod.rs +--- + diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_5.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_5.snap new file mode 100644 index 0000000000000..036224812c4af --- /dev/null +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__ruf100_5.snap @@ -0,0 +1,50 @@ +--- +source: crates/ruff/src/rules/ruff/mod.rs +--- +RUF100_5.py:7:5: ERA001 [*] Found commented-out code + | +5 | # "key1": 123, # noqa: ERA001 +6 | # "key2": 456, # noqa +7 | # "key3": 789, + | ^^^^^^^^^^^^^^ ERA001 +8 | } + | + = help: Remove commented-out code + +ℹ Possible fix +4 4 | dictionary = { +5 5 | # "key1": 123, # noqa: ERA001 +6 6 | # "key2": 456, # noqa +7 |- # "key3": 789, +8 7 | } +9 8 | +10 9 | + +RUF100_5.py:11:1: ERA001 [*] Found commented-out code + | +11 | #import os # noqa: E501 + | ^^^^^^^^^^^^^^^^^^^^^^^^ ERA001 + | + = help: Remove commented-out code + +ℹ Possible fix +8 8 | } +9 9 | +10 10 | +11 |-#import os # noqa: E501 + +RUF100_5.py:11:13: RUF100 [*] Unused `noqa` directive (unused: `E501`) + | +11 | #import os # noqa: E501 + | ^^^^^^^^^^^^ RUF100 + | + = help: Remove unused `noqa` directive + +ℹ Fix +8 8 | } +9 9 | +10 10 | +11 |-#import os # noqa: E501 + 11 |+#import os + + diff --git a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs index 122e740a5c057..3a55d2535ea2e 100644 --- a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs +++ b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs @@ -66,7 +66,7 @@ pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Exce for expr in calls { if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = expr.func.as_ref() { if attr == "error" { - if exc_info(&expr.keywords, checker.semantic()).is_none() { + if exc_info(&expr.arguments, checker.semantic()).is_none() { checker .diagnostics .push(Diagnostic::new(ErrorInsteadOfException, expr.range())); diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs index 51db4d53f054d..aadfa930c49f7 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_args.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; - use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Arguments, Constant, Expr, Ranged}; use crate::checkers::ast::Checker; @@ -17,6 +16,10 @@ use crate::checkers::ast::Checker; /// If the exception message is instead defined within the exception class, it /// will be consistent across all `raise` invocations. /// +/// This rule is not enforced for some built-in exceptions that are commonly +/// raised with a message and would be unusual to subclass, such as +/// `NotImplementedError`. +/// /// ## Example /// ```python /// class CantBeNegative(Exception): @@ -49,23 +52,54 @@ impl Violation for RaiseVanillaArgs { } } -fn any_string(expr: &Expr, predicate: F) -> bool -where - F: (Fn(&str) -> bool) + Copy, -{ +/// TRY003 +pub(crate) fn raise_vanilla_args(checker: &mut Checker, expr: &Expr) { + let Expr::Call(ast::ExprCall { + func, + arguments: Arguments { args, .. }, + .. + }) = expr + else { + return; + }; + + let Some(arg) = args.first() else { + return; + }; + + // Ignore some built-in exceptions that don't make sense to subclass, like + // `NotImplementedError`. + if checker + .semantic() + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "NotImplementedError"])) + { + return; + } + + if contains_message(arg) { + checker + .diagnostics + .push(Diagnostic::new(RaiseVanillaArgs, expr.range())); + } +} + +/// Returns `true` if an expression appears to be an exception message (i.e., a string with +/// some whitespace). +fn contains_message(expr: &Expr) -> bool { match expr { - Expr::JoinedStr(ast::ExprJoinedStr { values, range: _ }) => { + Expr::FString(ast::ExprFString { values, .. }) => { for value in values { - if any_string(value, predicate) { + if contains_message(value) { return true; } } } Expr::Constant(ast::ExprConstant { - value: Constant::Str(val), + value: Constant::Str(value), .. }) => { - if predicate(val.as_str()) { + if value.chars().any(char::is_whitespace) { return true; } } @@ -74,16 +108,3 @@ where false } - -/// TRY003 -pub(crate) fn raise_vanilla_args(checker: &mut Checker, expr: &Expr) { - if let Expr::Call(ast::ExprCall { args, .. }) = expr { - if let Some(arg) = args.first() { - if any_string(arg, |part| part.chars().any(char::is_whitespace)) { - checker - .diagnostics - .push(Diagnostic::new(RaiseVanillaArgs, expr.range())); - } - } - } -} diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs index 098bb127a6724..4edc10f21b656 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs @@ -69,9 +69,7 @@ pub(crate) fn raise_vanilla_class(checker: &mut Checker, expr: &Expr) { } else { expr }) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "Exception"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "Exception"])) { checker .diagnostics diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs b/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs index d807299f8a320..7748651468dc8 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_within_try.rs @@ -70,7 +70,7 @@ where fn visit_stmt(&mut self, stmt: &'b Stmt) { match stmt { Stmt::Raise(_) => self.raises.push(stmt), - Stmt::Try(_) | Stmt::TryStar(_) => (), + Stmt::Try(_) => (), _ => walk_stmt(self, stmt), } } @@ -114,7 +114,7 @@ pub(crate) fn raise_within_try(checker: &mut Checker, body: &[Stmt], handlers: & checker .semantic() .resolve_call_path(expr) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!(call_path.as_slice(), ["", "Exception" | "BaseException"]) }) }) diff --git a/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs b/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs index eabd70ed26d5d..523e97235e649 100644 --- a/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs +++ b/crates/ruff/src/rules/tryceratops/rules/reraise_no_cause.rs @@ -56,7 +56,7 @@ pub(crate) fn reraise_no_cause(checker: &mut Checker, body: &[Stmt]) { for (range, exc, cause) in raises { if cause.is_none() { - if exc.map_or(false, Expr::is_call_expr) { + if exc.is_some_and(Expr::is_call_expr) { checker .diagnostics .push(Diagnostic::new(ReraiseNoCause, range)); diff --git a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs index 85aa60eceb7f5..91e1d25b4cc48 100644 --- a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs +++ b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs @@ -55,7 +55,7 @@ where { fn visit_stmt(&mut self, stmt: &'b Stmt) { match stmt { - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } Stmt::Return(_) => self.returns.push(stmt), @@ -78,7 +78,7 @@ fn check_type_check_call(checker: &mut Checker, call: &Expr) -> bool { checker .semantic() .resolve_call_path(call) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["", "isinstance" | "issubclass" | "callable"] @@ -103,7 +103,7 @@ fn is_builtin_exception(checker: &mut Checker, exc: &Expr) -> bool { return checker .semantic() .resolve_call_path(exc) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), [ diff --git a/crates/ruff/src/rules/tryceratops/rules/useless_try_except.rs b/crates/ruff/src/rules/tryceratops/rules/useless_try_except.rs index b1ab793089b72..a7fc01fb988f5 100644 --- a/crates/ruff/src/rules/tryceratops/rules/useless_try_except.rs +++ b/crates/ruff/src/rules/tryceratops/rules/useless_try_except.rs @@ -53,7 +53,7 @@ pub(crate) fn useless_try_except(checker: &mut Checker, handlers: &[ExceptHandle if let Some(expr) = exc { // E.g., `except ... as e: raise e` if let Expr::Name(ast::ExprName { id, .. }) = expr.as_ref() { - if name.as_ref().map_or(false, |name| name.as_str() == id) { + if name.as_ref().is_some_and(|name| name.as_str() == id) { return Some(Diagnostic::new(UselessTryExcept, handler.range())); } } diff --git a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs index b55a7cfa9fbd0..800b36ff4f975 100644 --- a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs +++ b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs @@ -79,7 +79,7 @@ pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[ExceptHandl // Collect all referenced names in the `logging.exception` call. let names: Vec<&ast::ExprName> = { let mut names = Vec::new(); - for arg in &expr.args { + for arg in &expr.arguments.args { let mut visitor = NameVisitor::default(); visitor.visit_expr(arg); names.extend(visitor.names); diff --git a/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs b/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs index 9c881e1cb351b..70ff1e3c2137d 100644 --- a/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs +++ b/crates/ruff/src/rules/tryceratops/rules/verbose_raise.rs @@ -61,9 +61,6 @@ where } Stmt::Try(ast::StmtTry { body, finalbody, .. - }) - | Stmt::TryStar(ast::StmtTryStar { - body, finalbody, .. }) => { for stmt in body.iter().chain(finalbody.iter()) { walk_stmt(self, stmt); diff --git a/crates/ruff/src/settings/defaults.rs b/crates/ruff/src/settings/defaults.rs index 6ccc3bf09b9bd..a7ef3d3b88e67 100644 --- a/crates/ruff/src/settings/defaults.rs +++ b/crates/ruff/src/settings/defaults.rs @@ -24,8 +24,6 @@ pub const PREFIXES: &[RuleSelector] = &[ RuleSelector::Linter(Linter::Pyflakes), ]; -pub const TARGET_VERSION: PythonVersion = PythonVersion::Py310; - pub const TASK_TAGS: &[&str] = &["TODO", "FIXME", "XXX"]; pub static DUMMY_VARIABLE_RGX: Lazy = @@ -91,7 +89,7 @@ impl Default for Settings { respect_gitignore: true, src: vec![path_dedot::CWD.clone()], tab_size: TabSize::default(), - target_version: TARGET_VERSION, + target_version: PythonVersion::default(), task_tags: TASK_TAGS.iter().map(ToString::to_string).collect(), typing_modules: vec![], flake8_annotations: flake8_annotations::settings::Settings::default(), diff --git a/crates/ruff/src/settings/mod.rs b/crates/ruff/src/settings/mod.rs index 3dfc8372cd8c0..12bbd983347bc 100644 --- a/crates/ruff/src/settings/mod.rs +++ b/crates/ruff/src/settings/mod.rs @@ -183,7 +183,7 @@ impl Settings { .src .unwrap_or_else(|| vec![project_root.to_path_buf()]), project_root: project_root.to_path_buf(), - target_version: config.target_version.unwrap_or(defaults::TARGET_VERSION), + target_version: config.target_version.unwrap_or_default(), task_tags: config.task_tags.unwrap_or_else(|| { defaults::TASK_TAGS .iter() @@ -232,7 +232,8 @@ impl Settings { .unwrap_or_default(), flake8_pytest_style: config .flake8_pytest_style - .map(flake8_pytest_style::settings::Settings::from) + .map(flake8_pytest_style::settings::Settings::try_from) + .transpose()? .unwrap_or_default(), flake8_quotes: config .flake8_quotes @@ -298,6 +299,7 @@ impl Settings { pub fn for_rule(rule_code: Rule) -> Self { Self { rules: RuleTable::from_iter([rule_code]), + target_version: PythonVersion::latest(), ..Self::default() } } @@ -305,9 +307,17 @@ impl Settings { pub fn for_rules(rules: impl IntoIterator) -> Self { Self { rules: RuleTable::from_iter(rules), + target_version: PythonVersion::latest(), ..Self::default() } } + + /// Return the [`Settings`] after updating the target [`PythonVersion`]. + #[must_use] + pub fn with_target_version(mut self, target_version: PythonVersion) -> Self { + self.target_version = target_version; + self + } } impl From<&Configuration> for RuleTable { diff --git a/crates/ruff/src/settings/options.rs b/crates/ruff/src/settings/options.rs index 4fe3ecf819d30..d7e6c67edfb8e 100644 --- a/crates/ruff/src/settings/options.rs +++ b/crates/ruff/src/settings/options.rs @@ -312,13 +312,13 @@ pub struct Options { "# )] /// The line length to use when enforcing long-lines violations (like - /// `E501`). + /// `E501`). Must be greater than `0`. pub line_length: Option, #[option( default = "4", value_type = "int", example = r#" - tab_size = 8 + tab-size = 8 "# )] /// The tabulation size to calculate line length. @@ -456,7 +456,7 @@ pub struct Options { /// contained an `__init__.py` file. pub namespace_packages: Option>, #[option( - default = r#""py310""#, + default = r#""py38""#, value_type = r#""py37" | "py38" | "py39" | "py310" | "py311" | "py312""#, example = r#" # Always generate Python 3.7-compatible code. @@ -464,7 +464,11 @@ pub struct Options { "# )] /// The minimum Python version to target, e.g., when considering automatic - /// code upgrades, like rewriting type annotations. + /// code upgrades, like rewriting type annotations. Ruff will not propose + /// changes using features that are not available in the given version. + /// + /// For example, to represent supporting Python >=3.10 or ==3.10 + /// specify `target-version = "py310"`. /// /// If omitted, and Ruff is configured via a `pyproject.toml` file, the /// target version will be inferred from its `project.requires-python` @@ -596,7 +600,7 @@ pub struct Options { default = "{}", value_type = "dict[str, list[RuleSelector]]", example = r#" - # Also ignore `E401` in all `__init__.py` files. + # Also ignore `E402` in all `__init__.py` files. [tool.ruff.extend-per-file-ignores] "__init__.py" = ["E402"] "# diff --git a/crates/ruff/src/settings/types.rs b/crates/ruff/src/settings/types.rs index 82dc6fe34cd01..8461604425ba4 100644 --- a/crates/ruff/src/settings/types.rs +++ b/crates/ruff/src/settings/types.rs @@ -19,13 +19,25 @@ use crate::registry::RuleSet; use crate::rule_selector::RuleSelector; #[derive( - Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, CacheKey, EnumIter, + Clone, + Copy, + Debug, + PartialOrd, + Ord, + PartialEq, + Eq, + Default, + Serialize, + Deserialize, + CacheKey, + EnumIter, )] #[cfg_attr(feature = "clap", derive(clap::ValueEnum))] #[serde(rename_all = "lowercase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum PythonVersion { Py37, + #[default] Py38, Py39, Py310, @@ -41,6 +53,11 @@ impl From for Pep440Version { } impl PythonVersion { + /// Return the latest supported Python version. + pub const fn latest() -> Self { + Self::Py312 + } + pub const fn as_tuple(&self) -> (u32, u32) { match self { Self::Py37 => (3, 7), diff --git a/crates/ruff/src/source_kind.rs b/crates/ruff/src/source_kind.rs index ab63e89c28f2f..222a64847ceff 100644 --- a/crates/ruff/src/source_kind.rs +++ b/crates/ruff/src/source_kind.rs @@ -1,26 +1,38 @@ +use crate::autofix::source_map::SourceMap; use crate::jupyter::Notebook; #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum SourceKind { Python(String), - Jupyter(Notebook), + IpyNotebook(Notebook), } impl SourceKind { - /// Return the source content. - pub fn content(&self) -> &str { - match self { - SourceKind::Python(content) => content, - SourceKind::Jupyter(notebook) => notebook.content(), - } - } - - /// Return the [`Notebook`] if the source kind is [`SourceKind::Jupyter`]. + /// Return the [`Notebook`] if the source kind is [`SourceKind::IpyNotebook`]. pub fn notebook(&self) -> Option<&Notebook> { - if let Self::Jupyter(notebook) = self { + if let Self::IpyNotebook(notebook) = self { Some(notebook) } else { None } } + + #[must_use] + pub(crate) fn updated(&self, new_source: String, source_map: &SourceMap) -> Self { + match self { + SourceKind::IpyNotebook(notebook) => { + let mut cloned = notebook.clone(); + cloned.update(source_map, new_source); + SourceKind::IpyNotebook(cloned) + } + SourceKind::Python(_) => SourceKind::Python(new_source), + } + } + + pub fn source_code(&self) -> &str { + match self { + SourceKind::Python(source) => source, + SourceKind::IpyNotebook(notebook) => notebook.source_code(), + } + } } diff --git a/crates/ruff/src/test.rs b/crates/ruff/src/test.rs index 9e72487231e11..4c17d19e08c5d 100644 --- a/crates/ruff/src/test.rs +++ b/crates/ruff/src/test.rs @@ -1,23 +1,25 @@ #![cfg(any(test, fuzzing))] //! Helper functions for the tests of rule implementations. +use std::borrow::Cow; use std::path::Path; #[cfg(not(fuzzing))] use anyhow::Result; use itertools::Itertools; -use ruff_python_parser::lexer::LexResult; use rustc_hash::FxHashMap; use ruff_diagnostics::{AutofixKind, Diagnostic}; +use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; +use ruff_python_parser::lexer::LexResult; +use ruff_python_parser::AsMode; use ruff_python_trivia::textwrap::dedent; use ruff_source_file::{Locator, SourceFileBuilder}; use crate::autofix::{fix_file, FixResult}; use crate::directives; -#[cfg(not(fuzzing))] use crate::jupyter::Notebook; use crate::linter::{check_path, LinterResult}; use crate::message::{Emitter, EmitterContext, Message, TextEmitter}; @@ -30,7 +32,7 @@ use crate::source_kind::SourceKind; #[cfg(not(fuzzing))] pub(crate) fn read_jupyter_notebook(path: &Path) -> Result { let path = test_resource_path("fixtures/jupyter").join(path); - Notebook::read(&path).map_err(|err| { + Notebook::from_path(&path).map_err(|err| { anyhow::anyhow!( "Failed to read notebook file `{}`: {:?}", path.display(), @@ -49,11 +51,14 @@ pub(crate) fn test_resource_path(path: impl AsRef) -> std::path::PathBuf { pub(crate) fn test_path(path: impl AsRef, settings: &Settings) -> Result> { let path = test_resource_path("fixtures").join(path); let contents = std::fs::read_to_string(&path)?; - Ok(test_contents( - &mut SourceKind::Python(contents), - &path, - settings, - )) + Ok(test_contents(&SourceKind::Python(contents), &path, settings).0) +} + +#[cfg(not(fuzzing))] +pub(crate) struct TestedNotebook { + pub(crate) messages: Vec, + pub(crate) source_notebook: Notebook, + pub(crate) linted_notebook: Notebook, } #[cfg(not(fuzzing))] @@ -61,27 +66,36 @@ pub(crate) fn test_notebook_path( path: impl AsRef, expected: impl AsRef, settings: &Settings, -) -> Result<(Vec, SourceKind)> { - let mut source_kind = SourceKind::Jupyter(read_jupyter_notebook(path.as_ref())?); - let messages = test_contents(&mut source_kind, path.as_ref(), settings); +) -> Result { + let source_notebook = read_jupyter_notebook(path.as_ref())?; + + let source_kind = SourceKind::IpyNotebook(source_notebook); + let (messages, transformed) = test_contents(&source_kind, path.as_ref(), settings); let expected_notebook = read_jupyter_notebook(expected.as_ref())?; - if let SourceKind::Jupyter(notebook) = &source_kind { - assert_eq!(notebook.cell_offsets(), expected_notebook.cell_offsets()); - assert_eq!(notebook.index(), expected_notebook.index()); - assert_eq!(notebook.content(), expected_notebook.content()); - }; - Ok((messages, source_kind)) + let linted_notebook = transformed.into_owned().expect_ipy_notebook(); + + assert_eq!( + linted_notebook.cell_offsets(), + expected_notebook.cell_offsets() + ); + assert_eq!(linted_notebook.index(), expected_notebook.index()); + assert_eq!( + linted_notebook.source_code(), + expected_notebook.source_code() + ); + + Ok(TestedNotebook { + messages, + source_notebook: source_kind.expect_ipy_notebook(), + linted_notebook, + }) } /// Run [`check_path`] on a snippet of Python code. pub fn test_snippet(contents: &str, settings: &Settings) -> Vec { let path = Path::new(""); let contents = dedent(contents); - test_contents( - &mut SourceKind::Python(contents.to_string()), - path, - settings, - ) + test_contents(&SourceKind::Python(contents.into_owned()), path, settings).0 } thread_local! { @@ -98,10 +112,15 @@ pub(crate) fn max_iterations() -> usize { /// A convenient wrapper around [`check_path`], that additionally /// asserts that autofixes converge after a fixed number of iterations. -fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) -> Vec { - let contents = source_kind.content().to_string(); - let tokens: Vec = ruff_python_parser::tokenize(&contents); - let locator = Locator::new(&contents); +pub(crate) fn test_contents<'a>( + source_kind: &'a SourceKind, + path: &Path, + settings: &Settings, +) -> (Vec, Cow<'a, SourceKind>) { + let source_type = PySourceType::from(path); + let tokens: Vec = + ruff_python_parser::tokenize(source_kind.source_code(), source_type.as_mode()); + let locator = Locator::new(source_kind.source_code()); let stylist = Stylist::from_tokens(&tokens, &locator); let indexer = Indexer::from_tokens(&tokens, &locator); let directives = directives::extract_directives( @@ -125,6 +144,7 @@ fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) settings, flags::Noqa::Enabled, Some(source_kind), + source_type, ); let source_has_errors = error.is_some(); @@ -132,23 +152,24 @@ fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) // Detect autofixes that don't converge after multiple iterations. let mut iterations = 0; + let mut transformed = Cow::Borrowed(source_kind); + if diagnostics .iter() .any(|diagnostic| diagnostic.fix.is_some()) { let mut diagnostics = diagnostics.clone(); - let mut contents = contents.to_string(); while let Some(FixResult { code: fixed_contents, source_map, .. - }) = fix_file(&diagnostics, &Locator::new(&contents)) + }) = fix_file(&diagnostics, &Locator::new(transformed.source_code())) { if iterations < max_iterations() { iterations += 1; } else { - let output = print_diagnostics(diagnostics, path, &contents, source_kind); + let output = print_diagnostics(diagnostics, path, &transformed); panic!( "Failed to converge after {} iterations. This likely \ @@ -158,12 +179,11 @@ fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) ); } - if let Some(notebook) = source_kind.as_mut_jupyter() { - notebook.update(&source_map, &fixed_contents); - }; + transformed = Cow::Owned(transformed.updated(fixed_contents, &source_map)); - let tokens: Vec = ruff_python_parser::tokenize(&fixed_contents); - let locator = Locator::new(&fixed_contents); + let tokens: Vec = + ruff_python_parser::tokenize(transformed.source_code(), source_type.as_mode()); + let locator = Locator::new(transformed.source_code()); let stylist = Stylist::from_tokens(&tokens, &locator); let indexer = Indexer::from_tokens(&tokens, &locator); let directives = directives::extract_directives( @@ -187,17 +207,17 @@ fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) settings, flags::Noqa::Enabled, Some(source_kind), + source_type, ); if let Some(fixed_error) = fixed_error { if !source_has_errors { // Previous fix introduced a syntax error, abort - let fixes = print_diagnostics(diagnostics, path, &contents, source_kind); + let fixes = print_diagnostics(diagnostics, path, source_kind); let mut syntax_diagnostics = Vec::new(); syntax_error(&mut syntax_diagnostics, &fixed_error, &locator); - let syntax_errors = - print_diagnostics(syntax_diagnostics, path, &fixed_contents, source_kind); + let syntax_errors = print_diagnostics(syntax_diagnostics, path, &transformed); panic!( r#"Fixed source has a syntax error where the source document does not. This is a bug in one of the generated fixes: @@ -205,23 +225,23 @@ fn test_contents(source_kind: &mut SourceKind, path: &Path, settings: &Settings) Last generated fixes: {fixes} Source with applied fixes: -{fixed_contents}"# +{}"#, + transformed.source_code() ); } } diagnostics = fixed_diagnostics; - contents = fixed_contents.to_string(); } } let source_code = SourceFileBuilder::new( path.file_name().unwrap().to_string_lossy().as_ref(), - contents.as_str(), + source_kind.source_code(), ) .finish(); - diagnostics + let messages = diagnostics .into_iter() .map(|diagnostic| { let rule = diagnostic.kind.rule(); @@ -248,17 +268,17 @@ Source with applied fixes: Message::from_diagnostic(diagnostic, source_code.clone(), noqa) }) .sorted() - .collect() + .collect(); + (messages, transformed) } fn print_diagnostics( diagnostics: Vec, file_path: &Path, - source: &str, - source_kind: &SourceKind, + source: &SourceKind, ) -> String { let filename = file_path.file_name().unwrap().to_string_lossy(); - let source_file = SourceFileBuilder::new(filename.as_ref(), source).finish(); + let source_file = SourceFileBuilder::new(filename.as_ref(), source.source_code()).finish(); let messages: Vec<_> = diagnostics .into_iter() @@ -269,8 +289,8 @@ fn print_diagnostics( }) .collect(); - if source_kind.is_jupyter() { - print_jupyter_messages(&messages, &filename, source_kind) + if let Some(notebook) = source.notebook() { + print_jupyter_messages(&messages, &filename, notebook) } else { print_messages(&messages) } @@ -279,7 +299,7 @@ fn print_diagnostics( pub(crate) fn print_jupyter_messages( messages: &[Message], filename: &str, - source_kind: &SourceKind, + notebook: &Notebook, ) -> String { let mut output = Vec::new(); @@ -292,7 +312,7 @@ pub(crate) fn print_jupyter_messages( messages, &EmitterContext::new(&FxHashMap::from_iter([( filename.to_string(), - source_kind.clone(), + notebook.clone(), )])), ) .unwrap(); @@ -319,10 +339,10 @@ pub(crate) fn print_messages(messages: &[Message]) -> String { #[macro_export] macro_rules! assert_messages { - ($value:expr, $path:expr, $source_kind:expr) => {{ + ($value:expr, $path:expr, $notebook:expr) => {{ insta::with_settings!({ omit_expression => true }, { insta::assert_snapshot!( - $crate::test::print_jupyter_messages(&$value, &$path, &$source_kind) + $crate::test::print_jupyter_messages(&$value, &$path, &$notebook) ); }); }}; diff --git a/crates/ruff_benchmark/Cargo.toml b/crates/ruff_benchmark/Cargo.toml index 734471e1d2867..1d2baf66ddf35 100644 --- a/crates/ruff_benchmark/Cargo.toml +++ b/crates/ruff_benchmark/Cargo.toml @@ -37,6 +37,7 @@ ureq = "2.6.2" ruff.path = "../ruff" ruff_python_ast.path = "../ruff_python_ast" ruff_python_formatter = { path = "../ruff_python_formatter" } +ruff_python_index = { path = "../ruff_python_index" } ruff_python_parser = { path = "../ruff_python_parser" } criterion = { version = "0.5.1"} @@ -45,4 +46,3 @@ mimalloc = "0.1.34" [target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64")))'.dev-dependencies] tikv-jemallocator = "0.5.0" - diff --git a/crates/ruff_benchmark/benches/formatter.rs b/crates/ruff_benchmark/benches/formatter.rs index 74688bed09314..75f7298f4bae0 100644 --- a/crates/ruff_benchmark/benches/formatter.rs +++ b/crates/ruff_benchmark/benches/formatter.rs @@ -1,7 +1,13 @@ +use std::path::Path; +use std::time::Duration; + use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + use ruff_benchmark::{TestCase, TestCaseSpeed, TestFile, TestFileDownloadError}; -use ruff_python_formatter::{format_module, PyFormatOptions}; -use std::time::Duration; +use ruff_python_formatter::{format_node, PyFormatOptions}; +use ruff_python_index::CommentRangesBuilder; +use ruff_python_parser::lexer::lex; +use ruff_python_parser::{parse_tokens, Mode}; #[cfg(target_os = "windows")] #[global_allocator] @@ -40,6 +46,7 @@ fn benchmark_formatter(criterion: &mut Criterion) { for case in test_cases { group.throughput(Throughput::Bytes(case.code().len() as u64)); + group.measurement_time(match case.speed() { TestCaseSpeed::Fast => Duration::from_secs(5), TestCaseSpeed::Normal => Duration::from_secs(10), @@ -50,9 +57,28 @@ fn benchmark_formatter(criterion: &mut Criterion) { BenchmarkId::from_parameter(case.name()), &case, |b, case| { + let mut tokens = Vec::new(); + let mut comment_ranges = CommentRangesBuilder::default(); + + for result in lex(case.code(), Mode::Module) { + let (token, range) = result.expect("Input to be a valid python program."); + + comment_ranges.visit_token(&token, range); + tokens.push(Ok((token, range))); + } + + let comment_ranges = comment_ranges.finish(); + + // Parse the AST. + let python_ast = parse_tokens(tokens, Mode::Module, "") + .expect("Input to be a valid python program"); + b.iter(|| { - format_module(case.code(), PyFormatOptions::default()) - .expect("Formatting to succeed") + let options = PyFormatOptions::from_extension(Path::new(case.name())); + let formatted = format_node(&python_ast, &comment_ranges, case.code(), options) + .expect("Formatting to succeed"); + + formatted.print().expect("Printing to succeed") }); }, ); diff --git a/crates/ruff_benchmark/benches/linter.rs b/crates/ruff_benchmark/benches/linter.rs index 7abaa4fdafa25..796c96d21ab00 100644 --- a/crates/ruff_benchmark/benches/linter.rs +++ b/crates/ruff_benchmark/benches/linter.rs @@ -7,8 +7,10 @@ use criterion::{ use ruff::linter::lint_only; use ruff::settings::{flags, Settings}; +use ruff::source_kind::SourceKind; use ruff::RuleSelector; use ruff_benchmark::{TestCase, TestCaseSpeed, TestFile, TestFileDownloadError}; +use ruff_python_ast::PySourceType; #[cfg(target_os = "windows")] #[global_allocator] @@ -56,14 +58,16 @@ fn benchmark_linter(mut group: BenchmarkGroup, settings: &Settings) { BenchmarkId::from_parameter(case.name()), &case, |b, case| { + let kind = SourceKind::Python(case.code().to_string()); b.iter(|| { + let path = case.path(); let result = lint_only( - case.code(), - &case.path(), + &path, None, settings, flags::Noqa::Enabled, - None, + &kind, + PySourceType::from(path.as_path()), ); // Assert that file contains no parse errors diff --git a/crates/ruff_benchmark/benches/parser.rs b/crates/ruff_benchmark/benches/parser.rs index d7afdd106cc5a..fa3ed713266d4 100644 --- a/crates/ruff_benchmark/benches/parser.rs +++ b/crates/ruff_benchmark/benches/parser.rs @@ -4,8 +4,8 @@ use criterion::measurement::WallTime; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ruff_benchmark::{TestCase, TestCaseSpeed, TestFile, TestFileDownloadError}; use ruff_python_ast::statement_visitor::{walk_stmt, StatementVisitor}; -use ruff_python_ast::{Stmt, Suite}; -use ruff_python_parser::Parse; +use ruff_python_ast::Stmt; +use ruff_python_parser::parse_suite; #[cfg(target_os = "windows")] #[global_allocator] @@ -66,7 +66,7 @@ fn benchmark_parser(criterion: &mut Criterion) { &case, |b, case| { b.iter(|| { - let parsed = Suite::parse(case.code(), case.name()).unwrap(); + let parsed = parse_suite(case.code(), case.name()).unwrap(); let mut visitor = CountVisitor { count: 0 }; visitor.visit_body(&parsed); diff --git a/crates/ruff_cache/src/cache_key.rs b/crates/ruff_cache/src/cache_key.rs index e015112bda199..c62e580d1e2b3 100644 --- a/crates/ruff_cache/src/cache_key.rs +++ b/crates/ruff_cache/src/cache_key.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::hash_map::DefaultHasher; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::{Hash, Hasher}; +use std::num::NonZeroU8; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; @@ -205,6 +206,13 @@ impl CacheKey for i8 { } } +impl CacheKey for NonZeroU8 { + #[inline] + fn cache_key(&self, state: &mut CacheKeyHasher) { + state.write_u8(self.get()); + } +} + macro_rules! impl_cache_key_tuple { () => ( impl CacheKey for () { diff --git a/crates/ruff_cli/Cargo.toml b/crates/ruff_cli/Cargo.toml index 3e9faee31c3d5..6f17b684c7f0b 100644 --- a/crates/ruff_cli/Cargo.toml +++ b/crates/ruff_cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruff_cli" -version = "0.0.282" +version = "0.0.286" publish = false authors = { workspace = true } edition = { workspace = true } @@ -11,8 +11,6 @@ repository = { workspace = true } license = { workspace = true } readme = "../../README.md" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [[bin]] name = "ruff" diff --git a/crates/ruff_cli/src/bin/ruff.rs b/crates/ruff_cli/src/bin/ruff.rs index 97343ef79802d..81830ca251bf3 100644 --- a/crates/ruff_cli/src/bin/ruff.rs +++ b/crates/ruff_cli/src/bin/ruff.rs @@ -31,9 +31,10 @@ pub fn main() -> ExitCode { // default for convenience and backwards-compatibility, so we just // preprocess the arguments accordingly before passing them to Clap. if let Some(arg) = args.get(1) { - if arg.to_str().map_or(false, |arg| { - !Command::has_subcommand(rewrite_legacy_subcommand(arg)) - }) && arg != "-h" + if arg + .to_str() + .is_some_and(|arg| !Command::has_subcommand(rewrite_legacy_subcommand(arg))) + && arg != "-h" && arg != "--help" && arg != "-V" && arg != "--version" diff --git a/crates/ruff_cli/src/cache.rs b/crates/ruff_cli/src/cache.rs index 908a70c709198..b00326953a8f2 100644 --- a/crates/ruff_cli/src/cache.rs +++ b/crates/ruff_cli/src/cache.rs @@ -445,9 +445,9 @@ mod tests { } // Not stored in the cache. - expected_diagnostics.source_kind.clear(); - got_diagnostics.source_kind.clear(); - assert!(expected_diagnostics == got_diagnostics); + expected_diagnostics.notebooks.clear(); + got_diagnostics.notebooks.clear(); + assert_eq!(expected_diagnostics, got_diagnostics); } #[test] diff --git a/crates/ruff_cli/src/commands/run_stdin.rs b/crates/ruff_cli/src/commands/run_stdin.rs index f0ac60f32ac10..570ac21911034 100644 --- a/crates/ruff_cli/src/commands/run_stdin.rs +++ b/crates/ruff_cli/src/commands/run_stdin.rs @@ -37,7 +37,7 @@ pub(crate) fn run_stdin( let mut diagnostics = lint_stdin( filename, package_root, - &stdin, + stdin, &pyproject_config.settings.lib, noqa, autofix, diff --git a/crates/ruff_cli/src/diagnostics.rs b/crates/ruff_cli/src/diagnostics.rs index 54ce93a57dbeb..2d2f8ad974877 100644 --- a/crates/ruff_cli/src/diagnostics.rs +++ b/crates/ruff_cli/src/diagnostics.rs @@ -4,19 +4,17 @@ use std::fs::write; use std::io; use std::io::Write; use std::ops::AddAssign; +#[cfg(unix)] +use std::os::unix::fs::PermissionsExt; use std::path::Path; use anyhow::{anyhow, Context, Result}; use colored::Colorize; use filetime::FileTime; use log::{debug, error, warn}; -use ruff_text_size::{TextRange, TextSize}; use rustc_hash::FxHashMap; use similar::TextDiff; -#[cfg(unix)] -use std::os::unix::fs::PermissionsExt; -use crate::cache::Cache; use ruff::jupyter::{Cell, Notebook}; use ruff::linter::{lint_fix, lint_only, FixTable, FixerResult, LinterResult}; use ruff::logging::DisplayParseError; @@ -29,8 +27,12 @@ use ruff::{fs, IOError}; use ruff_diagnostics::Diagnostic; use ruff_macros::CacheKey; use ruff_python_ast::imports::ImportMap; -use ruff_python_stdlib::path::{is_jupyter_notebook, is_project_toml}; +use ruff_python_ast::PySourceType; +use ruff_python_stdlib::path::is_project_toml; use ruff_source_file::{LineIndex, SourceCode, SourceFileBuilder}; +use ruff_text_size::{TextRange, TextSize}; + +use crate::cache::Cache; #[derive(CacheKey)] pub(crate) struct FileCacheKey { @@ -62,7 +64,7 @@ pub(crate) struct Diagnostics { pub(crate) messages: Vec, pub(crate) fixed: FxHashMap, pub(crate) imports: ImportMap, - pub(crate) source_kind: FxHashMap, + pub(crate) notebooks: FxHashMap, } impl Diagnostics { @@ -71,7 +73,32 @@ impl Diagnostics { messages, fixed: FxHashMap::default(), imports, - source_kind: FxHashMap::default(), + notebooks: FxHashMap::default(), + } + } + + /// Generate [`Diagnostics`] based on an [`io::Error`]. + pub(crate) fn from_io_error(err: &io::Error, path: &Path, settings: &Settings) -> Self { + if settings.rules.enabled(Rule::IOError) { + let io_err = Diagnostic::new( + IOError { + message: err.to_string(), + }, + TextRange::default(), + ); + let dummy = SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish(); + Self::new( + vec![Message::from_diagnostic(io_err, dummy, TextSize::default())], + ImportMap::default(), + ) + } else { + warn!( + "{}{}{} {err}", + "Failed to lint ".bold(), + fs::relativize_path(path).bold(), + ":".bold() + ); + Self::default() } } } @@ -91,16 +118,18 @@ impl AddAssign for Diagnostics { } } } - self.source_kind.extend(other.source_kind); + self.notebooks.extend(other.notebooks); } } -/// Returns either an indexed python jupyter notebook or a diagnostic (which is empty if we skip) -fn load_jupyter_notebook(path: &Path) -> Result> { - let notebook = match Notebook::read(path) { +/// Read a Jupyter Notebook from disk. +/// +/// Returns either an indexed Python Jupyter Notebook or a diagnostic (which is empty if we skip). +fn notebook_from_path(path: &Path) -> Result> { + let notebook = match Notebook::from_path(path) { Ok(notebook) => { if !notebook.is_python_notebook() { - // Not a python notebook, this could e.g. be an R notebook which we want to just skip + // Not a python notebook, this could e.g. be an R notebook which we want to just skip. debug!( "Skipping {} because it's not a Python notebook", path.display() @@ -125,6 +154,44 @@ fn load_jupyter_notebook(path: &Path) -> Result> { Ok(notebook) } +/// Parse a Jupyter Notebook from a JSON string. +/// +/// Returns either an indexed Python Jupyter Notebook or a diagnostic (which is empty if we skip). +fn notebook_from_source_code( + source_code: &str, + path: Option<&Path>, +) -> Result> { + let notebook = match Notebook::from_source_code(source_code) { + Ok(notebook) => { + if !notebook.is_python_notebook() { + // Not a python notebook, this could e.g. be an R notebook which we want to just skip. + if let Some(path) = path { + debug!( + "Skipping {} because it's not a Python notebook", + path.display() + ); + } + return Err(Box::default()); + } + notebook + } + Err(diagnostic) => { + // Failed to read the jupyter notebook + return Err(Box::new(Diagnostics { + messages: vec![Message::from_diagnostic( + *diagnostic, + SourceFileBuilder::new(path.map(Path::to_string_lossy).unwrap_or_default(), "") + .finish(), + TextSize::default(), + )], + ..Diagnostics::default() + })); + } + }; + + Ok(notebook) +} + /// Lint the source code at the given `Path`. pub(crate) fn lint_path( path: &Path, @@ -161,31 +228,6 @@ pub(crate) fn lint_path( debug!("Checking: {}", path.display()); - // In case of an io error we want to exit early - let io_error_diagnostics = |err: io::Error, path: &Path| -> Diagnostics { - if settings.lib.rules.enabled(Rule::IOError) { - let io_err = Diagnostic::new( - IOError { - message: err.to_string(), - }, - TextRange::default(), - ); - let dummy = SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish(); - Diagnostics::new( - vec![Message::from_diagnostic(io_err, dummy, TextSize::default())], - ImportMap::default(), - ) - } else { - warn!( - "{}{}{} {err}", - "Failed to lint ".bold(), - fs::relativize_path(path).bold(), - ":".bold() - ); - Diagnostics::default() - } - }; - // We have to special case this here since the Python tokenizer doesn't work with TOML. if is_project_toml(path) { let messages = if settings @@ -197,7 +239,7 @@ pub(crate) fn lint_path( let contents = match std::fs::read_to_string(path) { Ok(contents) => contents, Err(err) => { - return Ok(io_error_diagnostics(err, path)); + return Ok(Diagnostics::from_io_error(&err, path, &settings.lib)); } }; let source_file = SourceFileBuilder::new(path.to_string_lossy(), contents).finish(); @@ -211,25 +253,20 @@ pub(crate) fn lint_path( }); } - // Read the file from disk - let mut source_kind = if is_jupyter_notebook(path) { - match load_jupyter_notebook(path) { - Ok(notebook) => SourceKind::Jupyter(notebook), - Err(diagnostic) => return Ok(*diagnostic), + // Extract the sources from the file. + let LintSources { + source_type, + source_kind, + } = match LintSources::try_from_path(path) { + Ok(sources) => sources, + Err(SourceExtractionError::Io(err)) => { + return Ok(Diagnostics::from_io_error(&err, path, &settings.lib)); + } + Err(SourceExtractionError::Diagnostics(diagnostics)) => { + return Ok(*diagnostics); } - } else { - // This is tested by ruff_cli integration test `unreadable_file` - let contents = match std::fs::read_to_string(path) { - Ok(contents) => contents, - Err(err) => { - return Ok(io_error_diagnostics(err, path)); - } - }; - SourceKind::Python(contents) }; - let contents = source_kind.content().to_string(); - // Lint the file. let ( LinterResult { @@ -243,41 +280,38 @@ pub(crate) fn lint_path( transformed, fixed, }) = lint_fix( - &contents, path, package, noqa, &settings.lib, - &mut source_kind, + &source_kind, + source_type, ) { if !fixed.is_empty() { match autofix { - flags::FixMode::Apply => match &source_kind { - SourceKind::Python(_) => { + flags::FixMode::Apply => match transformed.as_ref() { + SourceKind::Python(transformed) => { write(path, transformed.as_bytes())?; } - SourceKind::Jupyter(notebook) => { + SourceKind::IpyNotebook(notebook) => { notebook.write(path)?; } }, flags::FixMode::Diff => { - match &source_kind { - SourceKind::Python(_) => { + match transformed.as_ref() { + SourceKind::Python(transformed) => { let mut stdout = io::stdout().lock(); - TextDiff::from_lines(contents.as_str(), &transformed) + TextDiff::from_lines(source_kind.source_code(), transformed) .unified_diff() .header(&fs::relativize_path(path), &fs::relativize_path(path)) .to_writer(&mut stdout)?; stdout.write_all(b"\n")?; stdout.flush()?; } - SourceKind::Jupyter(dest_notebook) => { + SourceKind::IpyNotebook(dest_notebook) => { // We need to load the notebook again, since we might've // mutated it. - let src_notebook = match load_jupyter_notebook(path) { - Ok(notebook) => notebook, - Err(diagnostic) => return Ok(*diagnostic), - }; + let src_notebook = source_kind.as_ipy_notebook().unwrap(); let mut stdout = io::stdout().lock(); for ((idx, src_cell), dest_cell) in src_notebook .cells() @@ -329,24 +363,24 @@ pub(crate) fn lint_path( } else { // If we fail to autofix, lint the original source code. let result = lint_only( - &contents, path, package, &settings.lib, noqa, - Some(&source_kind), + &source_kind, + source_type, ); let fixed = FxHashMap::default(); (result, fixed) } } else { let result = lint_only( - &contents, path, package, &settings.lib, noqa, - Some(&source_kind), + &source_kind, + source_type, ); let fixed = FxHashMap::default(); (result, fixed) @@ -366,22 +400,31 @@ pub(crate) fn lint_path( "{}", DisplayParseError::new( err, - SourceCode::new(&contents, &LineIndex::from_source_text(&contents)), + SourceCode::new( + source_kind.source_code(), + &LineIndex::from_source_text(source_kind.source_code()) + ), Some(&source_kind), ) ); } + let notebooks = if let SourceKind::IpyNotebook(notebook) = source_kind { + FxHashMap::from_iter([( + path.to_str() + .ok_or_else(|| anyhow!("Unable to parse filename: {:?}", path))? + .to_string(), + notebook, + )]) + } else { + FxHashMap::default() + }; + Ok(Diagnostics { messages, fixed: FxHashMap::from_iter([(fs::relativize_path(path), fixed)]), imports, - source_kind: FxHashMap::from_iter([( - path.to_str() - .ok_or_else(|| anyhow!("Unable to parse filename: {:?}", path))? - .to_string(), - source_kind, - )]), + notebooks, }) } @@ -390,12 +433,26 @@ pub(crate) fn lint_path( pub(crate) fn lint_stdin( path: Option<&Path>, package: Option<&Path>, - contents: &str, + contents: String, settings: &Settings, noqa: flags::Noqa, autofix: flags::FixMode, ) -> Result { - let mut source_kind = SourceKind::Python(contents.to_string()); + // Extract the sources from the file. + let LintSources { + source_type, + source_kind, + } = match LintSources::try_from_source_code(contents, path) { + Ok(sources) => sources, + Err(SourceExtractionError::Io(err)) => { + // SAFETY: An `io::Error` can only occur if we're reading from a path. + return Ok(Diagnostics::from_io_error(&err, path.unwrap(), settings)); + } + Err(SourceExtractionError::Diagnostics(diagnostics)) => { + return Ok(*diagnostics); + } + }; + // Lint the inputs. let ( LinterResult { @@ -409,22 +466,25 @@ pub(crate) fn lint_stdin( transformed, fixed, }) = lint_fix( - contents, path.unwrap_or_else(|| Path::new("-")), package, noqa, settings, - &mut source_kind, + &source_kind, + source_type, ) { match autofix { flags::FixMode::Apply => { // Write the contents to stdout, regardless of whether any errors were fixed. - io::stdout().write_all(transformed.as_bytes())?; + io::stdout().write_all(transformed.source_code().as_bytes())?; } flags::FixMode::Diff => { // But only write a diff if it's non-empty. if !fixed.is_empty() { - let text_diff = TextDiff::from_lines(contents, &transformed); + let text_diff = TextDiff::from_lines( + source_kind.source_code(), + transformed.source_code(), + ); let mut unified_diff = text_diff.unified_diff(); if let Some(path) = path { unified_diff @@ -444,30 +504,30 @@ pub(crate) fn lint_stdin( } else { // If we fail to autofix, lint the original source code. let result = lint_only( - contents, path.unwrap_or_else(|| Path::new("-")), package, settings, noqa, - Some(&source_kind), + &source_kind, + source_type, ); let fixed = FxHashMap::default(); // Write the contents to stdout anyway. if autofix.is_apply() { - io::stdout().write_all(contents.as_bytes())?; + io::stdout().write_all(source_kind.source_code().as_bytes())?; } (result, fixed) } } else { let result = lint_only( - contents, path.unwrap_or_else(|| Path::new("-")), package, settings, noqa, - Some(&source_kind), + &source_kind, + source_type, ); let fixed = FxHashMap::default(); (result, fixed) @@ -489,22 +549,94 @@ pub(crate) fn lint_stdin( fixed, )]), imports, - source_kind: FxHashMap::default(), + notebooks: FxHashMap::default(), }) } +#[derive(Debug)] +struct LintSources { + /// The "type" of source code, e.g. `.py`, `.pyi`, `.ipynb`, etc. + source_type: PySourceType, + /// The "kind" of source, e.g. Python file, Jupyter Notebook, etc. + source_kind: SourceKind, +} + +impl LintSources { + /// Extract the lint [`LintSources`] from the given file path. + fn try_from_path(path: &Path) -> Result { + let source_type = PySourceType::from(path); + + // Read the file from disk. + if source_type.is_ipynb() { + let notebook = notebook_from_path(path).map_err(SourceExtractionError::Diagnostics)?; + let source_kind = SourceKind::IpyNotebook(notebook); + Ok(LintSources { + source_type, + source_kind, + }) + } else { + // This is tested by ruff_cli integration test `unreadable_file` + let contents = std::fs::read_to_string(path).map_err(SourceExtractionError::Io)?; + Ok(LintSources { + source_type, + source_kind: SourceKind::Python(contents), + }) + } + } + + /// Extract the lint [`LintSources`] from the raw string contents, optionally accompanied by a + /// file path indicating the path to the file from which the contents were read. If provided, + /// the file path should be used for diagnostics, but not for reading the file from disk. + fn try_from_source_code( + source_code: String, + path: Option<&Path>, + ) -> Result { + let source_type = path.map(PySourceType::from).unwrap_or_default(); + + if source_type.is_ipynb() { + let notebook = notebook_from_source_code(&source_code, path) + .map_err(SourceExtractionError::Diagnostics)?; + let source_kind = SourceKind::IpyNotebook(notebook); + Ok(LintSources { + source_type, + source_kind, + }) + } else { + Ok(LintSources { + source_type, + source_kind: SourceKind::Python(source_code), + }) + } + } +} + +#[derive(Debug)] +enum SourceExtractionError { + /// The extraction failed due to an [`io::Error`]. + Io(io::Error), + /// The extraction failed, and generated [`Diagnostics`] to report. + Diagnostics(Box), +} + #[cfg(test)] mod tests { use std::path::Path; - use crate::diagnostics::{load_jupyter_notebook, Diagnostics}; + use crate::diagnostics::{notebook_from_path, notebook_from_source_code, Diagnostics}; #[test] fn test_r() { let path = Path::new("../ruff/resources/test/fixtures/jupyter/R.ipynb"); - // No diagnostics is used as skip signal + // No diagnostics is used as skip signal. + assert_eq!( + notebook_from_path(path).unwrap_err(), + Box::::default() + ); + + let contents = std::fs::read_to_string(path).unwrap(); + // No diagnostics is used as skip signal. assert_eq!( - load_jupyter_notebook(path).unwrap_err(), + notebook_from_source_code(&contents, Some(path)).unwrap_err(), Box::::default() ); } diff --git a/crates/ruff_cli/src/lib.rs b/crates/ruff_cli/src/lib.rs index edfb43f5de3ad..a6d8a6f3785c3 100644 --- a/crates/ruff_cli/src/lib.rs +++ b/crates/ruff_cli/src/lib.rs @@ -90,12 +90,11 @@ fn is_stdin(files: &[PathBuf], stdin_filename: Option<&Path>) -> bool { return true; } + let [file] = files else { + return false; + }; // If the user provided exactly `-`, read from standard input. - if files.len() == 1 && files[0] == Path::new("-") { - return true; - } - - false + file == Path::new("-") } pub fn run( @@ -161,25 +160,20 @@ fn format(files: &[PathBuf]) -> Result { internal use only." ); - let format_code = |code: &str| { - // dummy, to check that the function was actually called - let contents = code.replace("# DEL", ""); - // real formatting that is currently a passthrough - format_module(&contents, PyFormatOptions::default()) - }; - match &files { // Check if we should read from stdin [path] if path == Path::new("-") => { let unformatted = read_from_stdin()?; - let formatted = format_code(&unformatted)?; + let options = PyFormatOptions::from_extension(Path::new("stdin.py")); + let formatted = format_module(&unformatted, options)?; stdout().lock().write_all(formatted.as_code().as_bytes())?; } _ => { for file in files { let unformatted = std::fs::read_to_string(file) .with_context(|| format!("Could not read {}: ", file.display()))?; - let formatted = format_code(&unformatted)?; + let options = PyFormatOptions::from_extension(file); + let formatted = format_module(&unformatted, options)?; std::fs::write(file, formatted.as_code().as_bytes()) .with_context(|| format!("Could not write to {}, exiting", file.display()))?; } diff --git a/crates/ruff_cli/src/printer.rs b/crates/ruff_cli/src/printer.rs index c1a06088909ad..ba42b7d98faa9 100644 --- a/crates/ruff_cli/src/printer.rs +++ b/crates/ruff_cli/src/printer.rs @@ -177,7 +177,7 @@ impl Printer { return Ok(()); } - let context = EmitterContext::new(&diagnostics.source_kind); + let context = EmitterContext::new(&diagnostics.notebooks); match self.format { SerializationFormat::Json => { @@ -364,7 +364,7 @@ impl Printer { writeln!(writer)?; } - let context = EmitterContext::new(&diagnostics.source_kind); + let context = EmitterContext::new(&diagnostics.notebooks); TextEmitter::default() .with_show_fix_status(show_fix_status(self.autofix_level)) .with_show_source(self.flags.intersects(Flags::SHOW_SOURCE)) diff --git a/crates/ruff_cli/tests/black_compatibility_test.rs b/crates/ruff_cli/tests/black_compatibility_test.rs index 39f5ba54973c1..a09cb6185ae5f 100644 --- a/crates/ruff_cli/tests/black_compatibility_test.rs +++ b/crates/ruff_cli/tests/black_compatibility_test.rs @@ -166,7 +166,7 @@ fn test_ruff_black_compatibility() -> Result<()> { entry .path() .extension() - .map_or(false, |ext| ext == "py" || ext == "pyi") + .is_some_and(|ext| ext == "py" || ext == "pyi") && !excludes.contains(&entry.path().file_name().unwrap().to_str().unwrap()) }); diff --git a/crates/ruff_cli/tests/integration_test.rs b/crates/ruff_cli/tests/integration_test.rs index 4d62a835d487b..bbb88ad0ecc36 100644 --- a/crates/ruff_cli/tests/integration_test.rs +++ b/crates/ruff_cli/tests/integration_test.rs @@ -81,6 +81,48 @@ Found 1 error. Ok(()) } +#[test] +fn stdin_source_type() -> Result<()> { + // Raise `TCH` errors in `.py` files. + let mut cmd = Command::cargo_bin(BIN_NAME)?; + let output = cmd + .args([ + "-", + "--format", + "text", + "--stdin-filename", + "TCH.py", + "--isolated", + ]) + .write_stdin("import os\n") + .assert() + .failure(); + assert_eq!( + str::from_utf8(&output.get_output().stdout)?, + r#"TCH.py:1:8: F401 [*] `os` imported but unused +Found 1 error. +[*] 1 potentially fixable with the --fix option. +"# + ); + + // But not in `.pyi` files. + let mut cmd = Command::cargo_bin(BIN_NAME)?; + cmd.args([ + "-", + "--format", + "text", + "--stdin-filename", + "TCH.pyi", + "--isolated", + "--select", + "TCH", + ]) + .write_stdin("import os\n") + .assert() + .success(); + Ok(()) +} + #[cfg(unix)] #[test] fn stdin_json() -> Result<()> { diff --git a/crates/ruff_dev/Cargo.toml b/crates/ruff_dev/Cargo.toml index 505a375308ec5..ccf81d3c9e573 100644 --- a/crates/ruff_dev/Cargo.toml +++ b/crates/ruff_dev/Cargo.toml @@ -44,6 +44,11 @@ toml = { workspace = true, features = ["parse"] } tracing = { workspace = true } tracing-indicatif = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } +imara-diff = "0.1.5" + +[features] +# Turn off rayon for profiling +singlethreaded = [] [dev-dependencies] indoc = "2.0.3" diff --git a/crates/ruff_dev/src/format_dev.rs b/crates/ruff_dev/src/format_dev.rs index 149f0c7faf971..22151c7d46c31 100644 --- a/crates/ruff_dev/src/format_dev.rs +++ b/crates/ruff_dev/src/format_dev.rs @@ -1,7 +1,11 @@ use anyhow::{bail, format_err, Context, Error}; use clap::{CommandFactory, FromArgMatches}; use ignore::DirEntry; +use imara_diff::intern::InternedInput; +use imara_diff::sink::Counter; +use imara_diff::{diff, Algorithm}; use indicatif::ProgressStyle; +#[cfg_attr(feature = "singlethreaded", allow(unused_imports))] use rayon::iter::{IntoParallelIterator, ParallelIterator}; use ruff::logging::LogLevel; use ruff::resolver::python_files_in_path; @@ -22,7 +26,7 @@ use std::panic::catch_unwind; use std::path::{Path, PathBuf}; use std::process::ExitCode; use std::time::{Duration, Instant}; -use std::{fmt, fs, io}; +use std::{fmt, fs, io, iter}; use tempfile::NamedTempFile; use tracing::{debug, error, info, info_span}; use tracing_indicatif::span_ext::IndicatifSpanExt; @@ -99,16 +103,18 @@ impl Statistics { intersection, } } else { - let diff = TextDiff::from_lines(black, ruff); - let mut statistics = Self::default(); - for change in diff.iter_all_changes() { - match change.tag() { - ChangeTag::Delete => statistics.black_input += 1, - ChangeTag::Insert => statistics.ruff_output += 1, - ChangeTag::Equal => statistics.intersection += 1, - } + // `similar` was too slow (for some files >90% diffing instead of formatting) + let input = InternedInput::new(black, ruff); + let changes = diff(Algorithm::Histogram, &input, Counter::default()); + assert_eq!( + input.before.len() - (changes.removals as usize), + input.after.len() - (changes.insertions as usize) + ); + Self { + black_input: changes.removals, + ruff_output: changes.insertions, + intersection: u32::try_from(input.before.len()).unwrap() - changes.removals, } - statistics } } @@ -184,15 +190,32 @@ pub(crate) struct Args { /// Write all errors to this file in addition to stdout. Only used in multi-project mode. #[arg(long)] pub(crate) error_file: Option, + /// Write all log messages (same as cli) to this file + #[arg(long)] + pub(crate) log_file: Option, + /// Write a markdown table with the similarity indices to this file + #[arg(long)] + pub(crate) stats_file: Option, + /// Assert that there are exactly this many input files with errors. This catches regressions + /// (or improvements) in the parser. + #[arg(long)] + pub(crate) files_with_errors: Option, #[clap(flatten)] pub(crate) log_level_args: LogLevelArgs, } pub(crate) fn main(args: &Args) -> anyhow::Result { - setup_logging(&args.log_level_args); + setup_logging(&args.log_level_args, args.log_file.as_deref())?; + + let mut error_file = match &args.error_file { + Some(error_file) => Some(BufWriter::new( + File::create(error_file).context("Couldn't open error file")?, + )), + None => None, + }; let all_success = if args.multi_project { - format_dev_multi_project(args)? + format_dev_multi_project(args, error_file)? } else { let result = format_dev_project(&args.files, args.stability_check, args.write)?; let error_count = result.error_count(); @@ -200,15 +223,29 @@ pub(crate) fn main(args: &Args) -> anyhow::Result { if result.error_count() > 0 { error!(parent: None, "{}", result.display(args.format)); } + if let Some(error_file) = &mut error_file { + write!(error_file, "{}", result.display(args.format)).unwrap(); + } info!( parent: None, - "Found {} stability errors in {} files (similarity index {:.3}) in {:.2}s", + "Done: {} stability errors, {} files, similarity index {:.5}), took {:.2}s, {} input files contained syntax errors ", error_count, result.file_count, result.statistics.similarity_index(), result.duration.as_secs_f32(), + result.syntax_error_in_input, ); + if let Some(files_with_errors) = args.files_with_errors { + if result.syntax_error_in_input != files_with_errors { + error!( + "Expected {files_with_errors} input files with errors, found {}", + result.syntax_error_in_input + ); + return Ok(ExitCode::FAILURE); + } + } + error_count == 0 }; if all_success { @@ -218,7 +255,7 @@ pub(crate) fn main(args: &Args) -> anyhow::Result { } } -fn setup_logging(log_level_args: &LogLevelArgs) { +fn setup_logging(log_level_args: &LogLevelArgs, log_file: Option<&Path>) -> io::Result<()> { // Custom translation since we need the tracing type for `EnvFilter` let log_level = match LogLevel::from(log_level_args) { LogLevel::Default => tracing::Level::INFO, @@ -232,21 +269,35 @@ fn setup_logging(log_level_args: &LogLevelArgs) { .with_default_directive(log_level.into()) .parse_lossy("") }); - let indicatif_layer = IndicatifLayer::new(); + let indicatif_layer = IndicatifLayer::new().with_progress_style( + // Default without the spinner + ProgressStyle::with_template("{span_child_prefix} {span_name}{{{span_fields}}}").unwrap(), + ); let indicitif_compatible_writer_layer = tracing_subscriber::fmt::layer() .with_writer(indicatif_layer.get_stderr_writer()) .with_target(false); + let log_layer = log_file.map(File::create).transpose()?.map(|log_file| { + tracing_subscriber::fmt::layer() + .with_writer(log_file) + .with_ansi(false) + }); tracing_subscriber::registry() .with(filter_layer) .with(indicitif_compatible_writer_layer) .with(indicatif_layer) + .with(log_layer) .init(); + Ok(()) } /// Checks a directory of projects -fn format_dev_multi_project(args: &Args) -> anyhow::Result { +fn format_dev_multi_project( + args: &Args, + mut error_file: Option>, +) -> anyhow::Result { let mut total_errors = 0; let mut total_files = 0; + let mut total_syntax_error_in_input = 0; let start = Instant::now(); let mut project_paths = Vec::new(); @@ -269,28 +320,26 @@ fn format_dev_multi_project(args: &Args) -> anyhow::Result { pb_span.pb_set_length(project_paths.len() as u64); let pb_span_enter = pb_span.enter(); - let mut error_file = match &args.error_file { - Some(error_file) => Some(BufWriter::new( - File::create(error_file).context("Couldn't open error file")?, - )), - None => None, - }; + let mut results = Vec::new(); for project_path in project_paths { - info!(parent: None, "Starting {}", project_path.display()); + debug!(parent: None, "Starting {}", project_path.display()); match format_dev_project(&[project_path.clone()], args.stability_check, args.write) { Ok(result) => { total_errors += result.error_count(); total_files += result.file_count; + total_syntax_error_in_input += result.syntax_error_in_input; info!( parent: None, - "Finished {}: {} files, similarity index {:.3}, {:.2}s", + "Finished {}: {} stability errors, {} files, similarity index {:.5}), took {:.2}s, {} input files contained syntax errors ", project_path.display(), + result.error_count(), result.file_count, result.statistics.similarity_index(), result.duration.as_secs_f32(), + result.syntax_error_in_input, ); if result.error_count() > 0 { error!( @@ -301,8 +350,8 @@ fn format_dev_multi_project(args: &Args) -> anyhow::Result { } if let Some(error_file) = &mut error_file { write!(error_file, "{}", result.display(args.format)).unwrap(); - error_file.flush().unwrap(); } + results.push(result); pb_span.pb_inc(1); } @@ -320,10 +369,49 @@ fn format_dev_multi_project(args: &Args) -> anyhow::Result { info!( parent: None, - "{total_errors} stability errors in {total_files} files in {}s", - duration.as_secs_f32() + "Finished: {total_errors} stability errors, {total_files} files, tool {}s, {total_syntax_error_in_input} input files contained syntax errors ", + duration.as_secs_f32(), ); + if let Some(stats_file) = &args.stats_file { + results.sort_by(|result1, result2| result1.name.cmp(&result2.name)); + let project_col_len = results + .iter() + .map(|result| result.name.len()) + .chain(iter::once("project".len())) + .max() + .unwrap_or_default(); + let mut stats_file = BufWriter::new(File::create(stats_file)?); + writeln!( + stats_file, + "| {:>>()? + #[cfg(not(feature = "singlethreaded"))] + let iter = { paths.into_par_iter() }; + #[cfg(feature = "singlethreaded")] + let iter = { paths.into_iter() }; + iter.map(|dir_entry| { + let result = format_dir_entry(dir_entry, stability_check, write, &black_options); + pb_span.pb_inc(1); + result + }) + .collect::>>()? }; let mut statistics = Statistics::default(); let mut formatted_counter = 0; + let mut syntax_error_in_input = 0; let mut diagnostics = Vec::new(); for (result, file) in results { formatted_counter += 1; match result { Ok(statistics_file) => statistics += statistics_file, - Err(error) => diagnostics.push(Diagnostic { file, error }), + Err(error) => { + match error { + CheckFileError::SyntaxErrorInInput(error) => { + // This is not our error + debug!( + parent: None, + "Syntax error in {}: {}", + file.display(), + error + ); + syntax_error_in_input += 1; + } + _ => diagnostics.push(Diagnostic { file, error }), + } + } } } let duration = start.elapsed(); + let name = files[0] + .file_name() + .unwrap_or(files[0].as_os_str()) + .to_string_lossy() + .to_string(); Ok(CheckRepoResult { + name, duration, file_count: formatted_counter, diagnostics, statistics, + syntax_error_in_input, }) } @@ -392,7 +504,7 @@ fn format_dir_entry( dir_entry: Result, stability_check: bool, write: bool, - options: &PyFormatOptions, + options: &BlackOptions, ) -> anyhow::Result<(Result, PathBuf), Error> { let dir_entry = match dir_entry.context("Iterating the files in the repository failed") { Ok(dir_entry) => dir_entry, @@ -405,39 +517,27 @@ fn format_dir_entry( } let file = dir_entry.path().to_path_buf(); + let options = options.to_py_format_options(&file); // Handle panics (mostly in `debug_assert!`) - let result = - match catch_unwind(|| format_dev_file(&file, stability_check, write, options.clone())) { - Ok(result) => match result { - Err(CheckFileError::SyntaxErrorInInput(error)) => { - // We don't care about this error, only log it - info!( - parent: None, - "Syntax error in {}: {}", - file.display(), - error - ); - Ok(Statistics::default()) - } - _ => result, - }, - Err(panic) => { - if let Some(message) = panic.downcast_ref::() { - Err(CheckFileError::Panic { - message: message.clone(), - }) - } else if let Some(&message) = panic.downcast_ref::<&str>() { - Err(CheckFileError::Panic { - message: message.to_string(), - }) - } else { - Err(CheckFileError::Panic { - // This should not happen, but it can - message: "(Panic didn't set a string message)".to_string(), - }) - } + let result = match catch_unwind(|| format_dev_file(&file, stability_check, write, options)) { + Ok(result) => result, + Err(panic) => { + if let Some(message) = panic.downcast_ref::() { + Err(CheckFileError::Panic { + message: message.clone(), + }) + } else if let Some(&message) = panic.downcast_ref::<&str>() { + Err(CheckFileError::Panic { + message: message.to_string(), + }) + } else { + Err(CheckFileError::Panic { + // This should not happen, but it can + message: "(Panic didn't set a string message)".to_string(), + }) } - }; + } + }; Ok((result, file)) } @@ -468,10 +568,12 @@ fn diff_show_only_changes( } struct CheckRepoResult { + name: String, duration: Duration, file_count: usize, diagnostics: Vec, statistics: Statistics, + syntax_error_in_input: u32, } impl CheckRepoResult { @@ -789,9 +891,8 @@ impl BlackOptions { Self::from_toml(&fs::read_to_string(&path)?, repo) } - fn to_py_format_options(&self) -> PyFormatOptions { - let mut options = PyFormatOptions::default(); - options + fn to_py_format_options(&self, file: &Path) -> PyFormatOptions { + PyFormatOptions::from_extension(file) .with_line_width( LineWidth::try_from(self.line_length).expect("Invalid line length limit"), ) @@ -799,8 +900,7 @@ impl BlackOptions { MagicTrailingComma::Ignore } else { MagicTrailingComma::Respect - }); - options + }) } } @@ -824,7 +924,7 @@ mod tests { "}; let options = BlackOptions::from_toml(toml, Path::new("pyproject.toml")) .unwrap() - .to_py_format_options(); + .to_py_format_options(Path::new("code_inline.py")); assert_eq!(options.line_width(), LineWidth::try_from(119).unwrap()); assert!(matches!( options.magic_trailing_comma(), @@ -843,7 +943,7 @@ mod tests { "#}; let options = BlackOptions::from_toml(toml, Path::new("pyproject.toml")) .unwrap() - .to_py_format_options(); + .to_py_format_options(Path::new("code_inline.py")); assert_eq!(options.line_width(), LineWidth::try_from(130).unwrap()); assert!(matches!( options.magic_trailing_comma(), diff --git a/crates/ruff_dev/src/generate_docs.rs b/crates/ruff_dev/src/generate_docs.rs index 93caebddcdba7..14e18a0a7200e 100644 --- a/crates/ruff_dev/src/generate_docs.rs +++ b/crates/ruff_dev/src/generate_docs.rs @@ -81,7 +81,7 @@ fn process_documentation(documentation: &str, out: &mut String) { // a non-CommonMark-compliant Markdown parser, which doesn't support code // tags in link definitions // (see https://github.com/Python-Markdown/markdown/issues/280). - let documentation = Regex::new(r"\[`(.*?)`]($|[^\[])").unwrap().replace_all( + let documentation = Regex::new(r"\[`([^`]*?)`]($|[^\[])").unwrap().replace_all( documentation, |caps: &Captures| { format!( diff --git a/crates/ruff_dev/src/print_ast.rs b/crates/ruff_dev/src/print_ast.rs index 287f969fca048..14aa14bfac6d7 100644 --- a/crates/ruff_dev/src/print_ast.rs +++ b/crates/ruff_dev/src/print_ast.rs @@ -5,19 +5,26 @@ use std::fs; use std::path::PathBuf; use anyhow::Result; -use ruff_python_ast::Suite; -use ruff_python_parser::Parse; +use ruff_python_parser::{parse, Mode}; #[derive(clap::Args)] pub(crate) struct Args { /// Python file for which to generate the AST. #[arg(required = true)] file: PathBuf, + /// Run in Jupyter mode i.e., allow line magics. + #[arg(long)] + jupyter: bool, } pub(crate) fn main(args: &Args) -> Result<()> { let contents = fs::read_to_string(&args.file)?; - let python_ast = Suite::parse(&contents, &args.file.to_string_lossy())?; + let mode = if args.jupyter { + Mode::Jupyter + } else { + Mode::Module + }; + let python_ast = parse(&contents, mode, &args.file.to_string_lossy())?; println!("{python_ast:#?}"); Ok(()) } diff --git a/crates/ruff_dev/src/print_tokens.rs b/crates/ruff_dev/src/print_tokens.rs index 573337e3f7fc2..c3e17904bcb05 100644 --- a/crates/ruff_dev/src/print_tokens.rs +++ b/crates/ruff_dev/src/print_tokens.rs @@ -12,11 +12,19 @@ pub(crate) struct Args { /// Python file for which to generate the AST. #[arg(required = true)] file: PathBuf, + /// Run in Jupyter mode i.e., allow line magics (`%`, `!`, `?`, `/`, `,`, `;`). + #[arg(long)] + jupyter: bool, } pub(crate) fn main(args: &Args) -> Result<()> { let contents = fs::read_to_string(&args.file)?; - for (tok, range) in lexer::lex(&contents, Mode::Module).flatten() { + let mode = if args.jupyter { + Mode::Jupyter + } else { + Mode::Module + }; + for (tok, range) in lexer::lex(&contents, mode).flatten() { println!( "{start:#?} {tok:#?} {end:#?}", start = range.start(), diff --git a/crates/ruff_diagnostics/src/diagnostic.rs b/crates/ruff_diagnostics/src/diagnostic.rs index 419f048674c0d..19a5d3ec45468 100644 --- a/crates/ruff_diagnostics/src/diagnostic.rs +++ b/crates/ruff_diagnostics/src/diagnostic.rs @@ -1,10 +1,11 @@ use anyhow::Result; use log::error; -use ruff_text_size::{TextRange, TextSize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{Edit, Fix}; +use ruff_text_size::{TextRange, TextSize}; + +use crate::Fix; #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -35,20 +36,6 @@ impl Diagnostic { } } - /// Set the [`Fix`] used to fix the diagnostic. - #[inline] - pub fn set_fix(&mut self, fix: Fix) { - self.fix = Some(fix); - } - - /// Set the [`Fix`] used to fix the diagnostic. - #[inline] - #[deprecated(note = "Use `Diagnostic::set_fix` instead.")] - #[allow(deprecated)] - pub fn set_fix_from_edit(&mut self, edit: Edit) { - self.fix = Some(Fix::unspecified(edit)); - } - /// Consumes `self` and returns a new `Diagnostic` with the given `fix`. #[inline] #[must_use] @@ -57,10 +44,15 @@ impl Diagnostic { self } + /// Set the [`Fix`] used to fix the diagnostic. + #[inline] + pub fn set_fix(&mut self, fix: Fix) { + self.fix = Some(fix); + } + /// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`. /// Otherwise, log the error. #[inline] - #[allow(deprecated)] pub fn try_set_fix(&mut self, func: impl FnOnce() -> Result) { match func() { Ok(fix) => self.fix = Some(fix), @@ -68,14 +60,13 @@ impl Diagnostic { } } - /// Sets an [`Edit`] used to fix the diagnostic, if the provided function returns `Ok`. + /// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`. /// Otherwise, log the error. #[inline] - #[deprecated(note = "Use Diagnostic::try_set_fix instead")] - #[allow(deprecated)] - pub fn try_set_fix_from_edit(&mut self, func: impl FnOnce() -> Result) { + pub fn try_set_optional_fix(&mut self, func: impl FnOnce() -> Result>) { match func() { - Ok(edit) => self.fix = Some(Fix::unspecified(edit)), + Ok(None) => {} + Ok(Some(fix)) => self.fix = Some(fix), Err(err) => error!("Failed to create fix for {}: {}", self.kind.name, err), } } diff --git a/crates/ruff_formatter/Cargo.toml b/crates/ruff_formatter/Cargo.toml index 2f9c52ee06a26..a4cf1781966fd 100644 --- a/crates/ruff_formatter/Cargo.toml +++ b/crates/ruff_formatter/Cargo.toml @@ -17,9 +17,9 @@ drop_bomb = { version = "0.1.5" } rustc-hash = { workspace = true } schemars = { workspace = true, optional = true } serde = { workspace = true, optional = true } -tracing = { version = "0.1.37", default-features = false, features = ["std"] } -unicode-width = { version = "0.1.10" } static_assertions = "1.1.0" +tracing = { version = "0.1.37", default-features = false, features = ["std"] } +unicode-width = { workspace = true } [dev-dependencies] insta = { workspace = true } diff --git a/crates/ruff_formatter/src/arguments.rs b/crates/ruff_formatter/src/arguments.rs index 01ee8f91e8dfc..850a734f04b2a 100644 --- a/crates/ruff_formatter/src/arguments.rs +++ b/crates/ruff_formatter/src/arguments.rs @@ -3,8 +3,8 @@ use crate::FormatResult; use std::ffi::c_void; use std::marker::PhantomData; -/// Mono-morphed type to format an object. Used by the [crate::format!], [crate::format_args!], and -/// [crate::write!] macros. +/// Mono-morphed type to format an object. Used by the [`crate::format`!], [`crate::format_args`!], and +/// [`crate::write`!] macros. /// /// This struct is similar to a dynamic dispatch (using `dyn Format`) because it stores a pointer to the value. /// However, it doesn't store the pointer to `dyn Format`'s vtable, instead it statically resolves the function @@ -33,24 +33,25 @@ impl<'fmt, Context> Argument<'fmt, Context> { #[doc(hidden)] #[inline] pub fn new>(value: &'fmt F) -> Self { - #[inline(always)] + #[inline] fn formatter, Context>( ptr: *const c_void, fmt: &mut Formatter, ) -> FormatResult<()> { // SAFETY: Safe because the 'fmt lifetime is captured by the 'lifetime' field. - F::fmt(unsafe { &*(ptr as *const F) }, fmt) + #[allow(unsafe_code)] + F::fmt(unsafe { &*ptr.cast::() }, fmt) } Self { - value: value as *const F as *const c_void, + value: (value as *const F).cast::(), lifetime: PhantomData, formatter: formatter::, } } /// Formats the value stored by this argument using the given formatter. - #[inline(always)] + #[inline] pub(super) fn format(&self, f: &mut Formatter) -> FormatResult<()> { (self.formatter)(self.value, f) } @@ -60,8 +61,8 @@ impl<'fmt, Context> Argument<'fmt, Context> { /// /// The [`format_args!`] macro will safely create an instance of this structure. /// -/// You can use the `Arguments` that [`format_args!]` return in `Format` context as seen below. -/// It will call the `format` function for every of it's objects. +/// You can use the `Arguments` that [`format_args!`] return in `Format` context as seen below. +/// It will call the `format` function for each of its objects. /// /// ```rust /// use ruff_formatter::prelude::*; @@ -80,13 +81,14 @@ pub struct Arguments<'fmt, Context>(pub &'fmt [Argument<'fmt, Context>]); impl<'fmt, Context> Arguments<'fmt, Context> { #[doc(hidden)] - #[inline(always)] + #[inline] pub fn new(arguments: &'fmt [Argument<'fmt, Context>]) -> Self { Self(arguments) } /// Returns the arguments #[inline] + #[allow(clippy::trivially_copy_pass_by_ref)] // Bug in Clippy? Sizeof Arguments is 16 pub(super) fn items(&self) -> &'fmt [Argument<'fmt, Context>] { self.0 } @@ -101,7 +103,7 @@ impl Clone for Arguments<'_, Context> { } impl Format for Arguments<'_, Context> { - #[inline(always)] + #[inline] fn fmt(&self, formatter: &mut Formatter) -> FormatResult<()> { formatter.write_fmt(*self) } diff --git a/crates/ruff_formatter/src/buffer.rs b/crates/ruff_formatter/src/buffer.rs index 13cb5420856c9..d2eec095fbca1 100644 --- a/crates/ruff_formatter/src/buffer.rs +++ b/crates/ruff_formatter/src/buffer.rs @@ -1,21 +1,21 @@ use super::{write, Arguments, FormatElement}; use crate::format_element::Interned; use crate::prelude::LineMode; -use crate::{Format, FormatResult, FormatState}; +use crate::{FormatResult, FormatState}; use rustc_hash::FxHashMap; use std::any::{Any, TypeId}; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; -/// A trait for writing or formatting into [FormatElement]-accepting buffers or streams. +/// A trait for writing or formatting into [`FormatElement`]-accepting buffers or streams. pub trait Buffer { /// The context used during formatting type Context; - /// Writes a [crate::FormatElement] into this buffer, returning whether the write succeeded. + /// Writes a [`crate::FormatElement`] into this buffer, returning whether the write succeeded. /// /// # Errors - /// This function will return an instance of [crate::FormatError] on error. + /// This function will return an instance of [`crate::FormatError`] on error. /// /// # Examples /// @@ -25,11 +25,11 @@ pub trait Buffer { /// let mut state = FormatState::new(SimpleFormatContext::default()); /// let mut buffer = VecBuffer::new(&mut state); /// - /// buffer.write_element(FormatElement::StaticText { text: "test"}).unwrap(); + /// buffer.write_element(FormatElement::StaticText { text: "test"}); /// /// assert_eq!(buffer.into_vec(), vec![FormatElement::StaticText { text: "test" }]); /// ``` - fn write_element(&mut self, element: FormatElement) -> FormatResult<()>; + fn write_element(&mut self, element: FormatElement); /// Returns a slice containing all elements written into this buffer. /// @@ -122,7 +122,7 @@ impl BufferSnapshot { Err(err) => { panic!( "Tried to unwrap snapshot of type {:?} as {:?}", - err.type_id(), + (*err).type_id(), TypeId::of::() ) } @@ -135,8 +135,8 @@ impl BufferSnapshot { impl + ?Sized, Context> Buffer for &mut W { type Context = Context; - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - (**self).write_element(element) + fn write_element(&mut self, element: FormatElement) { + (**self).write_element(element); } fn elements(&self) -> &[FormatElement] { @@ -160,7 +160,7 @@ impl + ?Sized, Context> Buffer for &mut W { } fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - (**self).restore_snapshot(snapshot) + (**self).restore_snapshot(snapshot); } } @@ -218,10 +218,8 @@ impl DerefMut for VecBuffer<'_, Context> { impl Buffer for VecBuffer<'_, Context> { type Context = Context; - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { + fn write_element(&mut self, element: FormatElement) { self.elements.push(element); - - Ok(()) } fn elements(&self) -> &[FormatElement] { @@ -252,140 +250,6 @@ Make sure that you take and restore the snapshot in order and that this snapshot } } -/// This struct wraps an existing buffer and emits a preamble text when the first text is written. -/// -/// This can be useful if you, for example, want to write some content if what gets written next isn't empty. -/// -/// # Examples -/// -/// ``` -/// use ruff_formatter::{FormatState, Formatted, PreambleBuffer, SimpleFormatContext, VecBuffer, write}; -/// use ruff_formatter::prelude::*; -/// -/// struct Preamble; -/// -/// impl Format for Preamble { -/// fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { -/// write!(f, [text("# heading"), hard_line_break()]) -/// } -/// } -/// -/// # fn main() -> FormatResult<()> { -/// let mut state = FormatState::new(SimpleFormatContext::default()); -/// let mut buffer = VecBuffer::new(&mut state); -/// -/// { -/// let mut with_preamble = PreambleBuffer::new(&mut buffer, Preamble); -/// -/// write!(&mut with_preamble, [text("this text will be on a new line")])?; -/// } -/// -/// let formatted = Formatted::new(Document::from(buffer.into_vec()), SimpleFormatContext::default()); -/// assert_eq!("# heading\nthis text will be on a new line", formatted.print()?.as_code()); -/// -/// # Ok(()) -/// # } -/// ``` -/// -/// The pre-amble does not get written if no content is written to the buffer. -/// -/// ``` -/// use ruff_formatter::{FormatState, Formatted, PreambleBuffer, SimpleFormatContext, VecBuffer, write}; -/// use ruff_formatter::prelude::*; -/// -/// struct Preamble; -/// -/// impl Format for Preamble { -/// fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { -/// write!(f, [text("# heading"), hard_line_break()]) -/// } -/// } -/// -/// # fn main() -> FormatResult<()> { -/// let mut state = FormatState::new(SimpleFormatContext::default()); -/// let mut buffer = VecBuffer::new(&mut state); -/// { -/// let mut with_preamble = PreambleBuffer::new(&mut buffer, Preamble); -/// } -/// -/// let formatted = Formatted::new(Document::from(buffer.into_vec()), SimpleFormatContext::default()); -/// assert_eq!("", formatted.print()?.as_code()); -/// # Ok(()) -/// # } -/// ``` -pub struct PreambleBuffer<'buf, Preamble, Context> { - /// The wrapped buffer - inner: &'buf mut dyn Buffer, - - /// The pre-amble to write once the first content gets written to this buffer. - preamble: Preamble, - - /// Whether some content (including the pre-amble) has been written at this point. - empty: bool, -} - -impl<'buf, Preamble, Context> PreambleBuffer<'buf, Preamble, Context> { - pub fn new(inner: &'buf mut dyn Buffer, preamble: Preamble) -> Self { - Self { - inner, - preamble, - empty: true, - } - } - - /// Returns `true` if the preamble has been written, `false` otherwise. - pub fn did_write_preamble(&self) -> bool { - !self.empty - } -} - -impl Buffer for PreambleBuffer<'_, Preamble, Context> -where - Preamble: Format, -{ - type Context = Context; - - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - if self.empty { - write!(self.inner, [&self.preamble])?; - self.empty = false; - } - - self.inner.write_element(element) - } - - fn elements(&self) -> &[FormatElement] { - self.inner.elements() - } - - fn state(&self) -> &FormatState { - self.inner.state() - } - - fn state_mut(&mut self) -> &mut FormatState { - self.inner.state_mut() - } - - fn snapshot(&self) -> BufferSnapshot { - BufferSnapshot::Any(Box::new(PreambleBufferSnapshot { - inner: self.inner.snapshot(), - empty: self.empty, - })) - } - - fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - let snapshot = snapshot.unwrap_any::(); - - self.empty = snapshot.empty; - self.inner.restore_snapshot(snapshot.inner); - } -} - -struct PreambleBufferSnapshot { - inner: BufferSnapshot, - empty: bool, -} - /// Buffer that allows you inspecting elements as they get written to the formatter. pub struct Inspect<'inner, Context, Inspector> { inner: &'inner mut dyn Buffer, @@ -404,9 +268,9 @@ where { type Context = Context; - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { + fn write_element(&mut self, element: FormatElement) { (self.inspector)(&element); - self.inner.write_element(element) + self.inner.write_element(element); } fn elements(&self) -> &[FormatElement] { @@ -426,7 +290,7 @@ where } fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - self.inner.restore_snapshot(snapshot) + self.inner.restore_snapshot(snapshot); } } @@ -508,68 +372,67 @@ fn clean_interned( interned: &Interned, interned_cache: &mut FxHashMap, ) -> Interned { - match interned_cache.get(interned) { - Some(cleaned) => cleaned.clone(), - None => { - // Find the first soft line break element or interned element that must be changed - let result = interned - .iter() - .enumerate() - .find_map(|(index, element)| match element { - FormatElement::Line(LineMode::Soft | LineMode::SoftOrSpace) => { - let mut cleaned = Vec::new(); - cleaned.extend_from_slice(&interned[..index]); - Some((cleaned, &interned[index..])) - } - FormatElement::Interned(inner) => { - let cleaned_inner = clean_interned(inner, interned_cache); - - if &cleaned_inner != inner { - let mut cleaned = Vec::with_capacity(interned.len()); - cleaned.extend_from_slice(&interned[..index]); - cleaned.push(FormatElement::Interned(cleaned_inner)); - Some((cleaned, &interned[index + 1..])) - } else { - None - } - } + if let Some(cleaned) = interned_cache.get(interned) { + cleaned.clone() + } else { + // Find the first soft line break element or interned element that must be changed + let result = interned + .iter() + .enumerate() + .find_map(|(index, element)| match element { + FormatElement::Line(LineMode::Soft | LineMode::SoftOrSpace) => { + let mut cleaned = Vec::new(); + cleaned.extend_from_slice(&interned[..index]); + Some((cleaned, &interned[index..])) + } + FormatElement::Interned(inner) => { + let cleaned_inner = clean_interned(inner, interned_cache); - _ => None, - }); - - let result = match result { - // Copy the whole interned buffer so that becomes possible to change the necessary elements. - Some((mut cleaned, rest)) => { - for element in rest { - let element = match element { - FormatElement::Line(LineMode::Soft) => continue, - FormatElement::Line(LineMode::SoftOrSpace) => FormatElement::Space, - FormatElement::Interned(interned) => { - FormatElement::Interned(clean_interned(interned, interned_cache)) - } - element => element.clone(), - }; - cleaned.push(element) + if &cleaned_inner == inner { + None + } else { + let mut cleaned = Vec::with_capacity(interned.len()); + cleaned.extend_from_slice(&interned[..index]); + cleaned.push(FormatElement::Interned(cleaned_inner)); + Some((cleaned, &interned[index + 1..])) } + } - Interned::new(cleaned) + _ => None, + }); + + let result = match result { + // Copy the whole interned buffer so that becomes possible to change the necessary elements. + Some((mut cleaned, rest)) => { + for element in rest { + let element = match element { + FormatElement::Line(LineMode::Soft) => continue, + FormatElement::Line(LineMode::SoftOrSpace) => FormatElement::Space, + FormatElement::Interned(interned) => { + FormatElement::Interned(clean_interned(interned, interned_cache)) + } + element => element.clone(), + }; + cleaned.push(element); } - // No change necessary, return existing interned element - None => interned.clone(), - }; - interned_cache.insert(interned.clone(), result.clone()); - result - } + Interned::new(cleaned) + } + // No change necessary, return existing interned element + None => interned.clone(), + }; + + interned_cache.insert(interned.clone(), result.clone()); + result } } impl Buffer for RemoveSoftLinesBuffer<'_, Context> { type Context = Context; - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { + fn write_element(&mut self, element: FormatElement) { let element = match element { - FormatElement::Line(LineMode::Soft) => return Ok(()), + FormatElement::Line(LineMode::Soft) => return, FormatElement::Line(LineMode::SoftOrSpace) => FormatElement::Space, FormatElement::Interned(interned) => { FormatElement::Interned(self.clean_interned(&interned)) @@ -577,7 +440,7 @@ impl Buffer for RemoveSoftLinesBuffer<'_, Context> { element => element, }; - self.inner.write_element(element) + self.inner.write_element(element); } fn elements(&self) -> &[FormatElement] { @@ -597,7 +460,7 @@ impl Buffer for RemoveSoftLinesBuffer<'_, Context> { } fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - self.inner.restore_snapshot(snapshot) + self.inner.restore_snapshot(snapshot); } } @@ -654,15 +517,13 @@ pub trait BufferExtensions: Buffer + Sized { } /// Writes a sequence of elements into this buffer. - fn write_elements(&mut self, elements: I) -> FormatResult<()> + fn write_elements(&mut self, elements: I) where I: IntoIterator, { - for element in elements.into_iter() { - self.write_element(element)?; + for element in elements { + self.write_element(element); } - - Ok(()) } } @@ -685,14 +546,14 @@ where } } - #[inline(always)] + #[inline] pub fn write_fmt(&mut self, arguments: Arguments) -> FormatResult<()> { self.buffer.write_fmt(arguments) } - #[inline(always)] - pub fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - self.buffer.write_element(element) + #[inline] + pub fn write_element(&mut self, element: FormatElement) { + self.buffer.write_element(element); } pub fn stop(self) -> Recorded<'buf> { diff --git a/crates/ruff_formatter/src/builders.rs b/crates/ruff_formatter/src/builders.rs index 8e5ed0b8a0e90..881a80e557cd6 100644 --- a/crates/ruff_formatter/src/builders.rs +++ b/crates/ruff_formatter/src/builders.rs @@ -8,6 +8,7 @@ use ruff_text_size::TextRange; use std::cell::Cell; use std::marker::PhantomData; use std::num::NonZeroU8; +#[allow(clippy::enum_glob_use)] use Tag::*; /// A line break that only gets printed if the enclosing `Group` doesn't fit on a single line. @@ -34,7 +35,7 @@ use Tag::*; /// # Ok(()) /// # } /// ``` -/// See [soft_line_break_or_space] if you want to insert a space between the elements if the enclosing +/// See [`soft_line_break_or_space`] if you want to insert a space between the elements if the enclosing /// `Group` fits on a single line. /// /// Soft line breaks are emitted if the enclosing `Group` doesn't fit on a single line @@ -202,7 +203,8 @@ impl Line { impl Format for Line { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Line(self.mode)) + f.write_element(FormatElement::Line(self.mode)); + Ok(()) } } @@ -217,7 +219,7 @@ impl std::fmt::Debug for Line { /// /// # Line feeds /// Tokens may contain line breaks but they must use the line feeds (`\n`). -/// The [crate::Printer] converts the line feed characters to the character specified in the [crate::PrinterOptions]. +/// The [`crate::Printer`] converts the line feed characters to the character specified in the [`crate::PrinterOptions`]. /// /// # Examples /// @@ -265,7 +267,8 @@ pub struct StaticText { impl Format for StaticText { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::StaticText { text: self.text }) + f.write_element(FormatElement::StaticText { text: self.text }); + Ok(()) } } @@ -325,7 +328,8 @@ pub struct SourcePosition(TextSize); impl Format for SourcePosition { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::SourcePosition(self.0)) + f.write_element(FormatElement::SourcePosition(self.0)); + Ok(()) } } @@ -345,12 +349,14 @@ pub struct DynamicText<'a> { impl Format for DynamicText<'_> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { if let Some(source_position) = self.position { - f.write_element(FormatElement::SourcePosition(source_position))?; + f.write_element(FormatElement::SourcePosition(source_position)); } f.write_element(FormatElement::DynamicText { text: self.text.to_string().into_boxed_str(), - }) + }); + + Ok(()) } } @@ -418,7 +424,9 @@ where f.write_element(FormatElement::SourceCodeSlice { slice, contains_newlines, - }) + }); + + Ok(()) } } @@ -465,9 +473,11 @@ pub struct LineSuffix<'a, Context> { impl Format for LineSuffix<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartLineSuffix))?; + f.write_element(FormatElement::Tag(StartLineSuffix)); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndLineSuffix)) + f.write_element(FormatElement::Tag(EndLineSuffix)); + + Ok(()) } } @@ -478,7 +488,7 @@ impl std::fmt::Debug for LineSuffix<'_, Context> { } /// Inserts a boundary for line suffixes that forces the printer to print all pending line suffixes. -/// Helpful if a line sufix shouldn't pass a certain point. +/// Helpful if a line suffix shouldn't pass a certain point. /// /// ## Examples /// @@ -512,7 +522,9 @@ pub struct LineSuffixBoundary; impl Format for LineSuffixBoundary { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::LineSuffixBoundary) + f.write_element(FormatElement::LineSuffixBoundary); + + Ok(()) } } @@ -520,7 +532,7 @@ impl Format for LineSuffixBoundary { /// /// This does not directly influence how this content will be printed, but some /// parts of the formatter may inspect the [labelled element](Tag::StartLabelled) -/// using [FormatElements::has_label]. +/// using [`FormatElements::has_label`]. /// /// ## Examples /// @@ -559,7 +571,7 @@ impl Format for LineSuffixBoundary { /// /// let recorded = recording.stop(); /// -/// let is_labelled = recorded.first().map_or(false, |element| element.has_label(LabelId::of(MyLabels::Main))); +/// let is_labelled = recorded.first().is_some_and( |element| element.has_label(LabelId::of(MyLabels::Main))); /// /// if is_labelled { /// write!(f, [text(" has label `Main`")]) @@ -597,9 +609,11 @@ pub struct FormatLabelled<'a, Context> { impl Format for FormatLabelled<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartLabelled(self.label_id)))?; + f.write_element(FormatElement::Tag(StartLabelled(self.label_id))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndLabelled)) + f.write_element(FormatElement::Tag(EndLabelled)); + + Ok(()) } } @@ -638,7 +652,9 @@ pub struct Space; impl Format for Space { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Space) + f.write_element(FormatElement::Space); + + Ok(()) } } @@ -648,7 +664,7 @@ impl Format for Space { /// the line breaks have to be manually added. /// /// This helper should be used only in rare cases, instead you should rely more on -/// [block_indent] and [soft_block_indent] +/// [`block_indent`] and [`soft_block_indent`] /// /// # Examples /// @@ -694,9 +710,11 @@ pub struct Indent<'a, Context> { impl Format for Indent<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartIndent))?; + f.write_element(FormatElement::Tag(StartIndent)); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndIndent)) + f.write_element(FormatElement::Tag(EndIndent)); + + Ok(()) } } @@ -765,9 +783,11 @@ pub struct Dedent<'a, Context> { impl Format for Dedent<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartDedent(self.mode)))?; + f.write_element(FormatElement::Tag(StartDedent(self.mode))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndDedent)) + f.write_element(FormatElement::Tag(EndDedent)); + + Ok(()) } } @@ -950,9 +970,11 @@ pub struct Align<'a, Context> { impl Format for Align<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartAlign(tag::Align(self.count))))?; + f.write_element(FormatElement::Tag(StartAlign(tag::Align(self.count)))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndAlign)) + f.write_element(FormatElement::Tag(EndAlign)); + + Ok(()) } } @@ -970,7 +992,7 @@ impl std::fmt::Debug for Align<'_, Context> { /// Block indents indent a block of code, such as in a function body, and therefore insert a line /// break before and after the content. /// -/// Doesn't create an indention if the passed in content is [FormatElement.is_empty]. +/// Doesn't create an indention if the passed in content is [`FormatElement.is_empty`]. /// /// # Examples /// @@ -1170,13 +1192,13 @@ impl Format for BlockIndent<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let snapshot = f.snapshot(); - f.write_element(FormatElement::Tag(StartIndent))?; + f.write_element(FormatElement::Tag(StartIndent)); match self.mode { IndentMode::Soft => write!(f, [soft_line_break()])?, IndentMode::Block => write!(f, [hard_line_break()])?, IndentMode::SoftLineOrSpace | IndentMode::SoftSpace => { - write!(f, [soft_line_break_or_space()])? + write!(f, [soft_line_break_or_space()])?; } } @@ -1191,7 +1213,7 @@ impl Format for BlockIndent<'_, Context> { return Ok(()); } - f.write_element(FormatElement::Tag(EndIndent))?; + f.write_element(FormatElement::Tag(EndIndent)); match self.mode { IndentMode::Soft => write!(f, [soft_line_break()]), @@ -1374,17 +1396,19 @@ pub struct Group<'a, Context> { } impl Group<'_, Context> { + #[must_use] pub fn with_group_id(mut self, group_id: Option) -> Self { self.group_id = group_id; self } - /// Changes the [PrintMode] of the group from [`Flat`](PrintMode::Flat) to [`Expanded`](PrintMode::Expanded). + /// Changes the [`PrintMode`] of the group from [`Flat`](PrintMode::Flat) to [`Expanded`](PrintMode::Expanded). /// The result is that any soft-line break gets printed as a regular line break. /// - /// This is useful for content rendered inside of a [FormatElement::BestFitting] that prints each variant - /// in [PrintMode::Flat] to change some content to be printed in [`Expanded`](PrintMode::Expanded) regardless. + /// This is useful for content rendered inside of a [`FormatElement::BestFitting`] that prints each variant + /// in [`PrintMode::Flat`] to change some content to be printed in [`Expanded`](PrintMode::Expanded) regardless. /// See the documentation of the [`best_fitting`] macro for an example. + #[must_use] pub fn should_expand(mut self, should_expand: bool) -> Self { self.should_expand = should_expand; self @@ -1393,18 +1417,21 @@ impl Group<'_, Context> { impl Format for Group<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - let mode = match self.should_expand { - true => GroupMode::Expand, - false => GroupMode::Flat, + let mode = if self.should_expand { + GroupMode::Expand + } else { + GroupMode::Flat }; f.write_element(FormatElement::Tag(StartGroup( tag::Group::new().with_id(self.group_id).with_mode(mode), - )))?; + ))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndGroup)) + f.write_element(FormatElement::Tag(EndGroup)); + + Ok(()) } } @@ -1532,9 +1559,11 @@ impl Format for ConditionalGroup<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { f.write_element(FormatElement::Tag(StartConditionalGroup( tag::ConditionalGroup::new(self.condition), - )))?; + ))); f.write_fmt(Arguments::from(&self.content))?; - f.write_element(FormatElement::Tag(EndConditionalGroup)) + f.write_element(FormatElement::Tag(EndConditionalGroup)); + + Ok(()) } } @@ -1592,7 +1621,9 @@ pub struct ExpandParent; impl Format for ExpandParent { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::ExpandParent) + f.write_element(FormatElement::ExpandParent); + + Ok(()) } } @@ -1602,7 +1633,7 @@ impl Format for ExpandParent { /// /// The element has no special meaning if used outside of a `Group`. In that case, the content is always emitted. /// -/// If you're looking for a way to only print something if the `Group` fits on a single line see [self::if_group_fits_on_line]. +/// If you're looking for a way to only print something if the `Group` fits on a single line see [`self::if_group_fits_on_line`]. /// /// # Examples /// @@ -1684,7 +1715,7 @@ where /// Adds a conditional content specific for `Group`s that fit on a single line. The content isn't /// emitted for `Group`s spanning multiple lines. /// -/// See [if_group_breaks] if you're looking for a way to print content only for groups spanning multiple lines. +/// See [`if_group_breaks`] if you're looking for a way to print content only for groups spanning multiple lines. /// /// # Examples /// @@ -1823,6 +1854,7 @@ impl IfGroupBreaks<'_, Context> { /// # Ok(()) /// # } /// ``` + #[must_use] pub fn with_group_id(mut self, group_id: Option) -> Self { self.group_id = group_id; self @@ -1833,9 +1865,11 @@ impl Format for IfGroupBreaks<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { f.write_element(FormatElement::Tag(StartConditionalContent( Condition::new(self.mode).with_group_id(self.group_id), - )))?; + ))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndConditionalContent)) + f.write_element(FormatElement::Tag(EndConditionalContent)); + + Ok(()) } } @@ -1855,7 +1889,7 @@ impl std::fmt::Debug for IfGroupBreaks<'_, Context> { /// Increases the indent level by one if the group with the specified id breaks. /// -/// This IR has the same semantics as using [if_group_breaks] and [if_group_fits_on_line] together. +/// This IR has the same semantics as using [`if_group_breaks`] and [`if_group_fits_on_line`] together. /// /// ``` /// # use ruff_formatter::prelude::*; @@ -1874,7 +1908,7 @@ impl std::fmt::Debug for IfGroupBreaks<'_, Context> { /// /// If you want to indent some content if the enclosing group breaks, use [`indent`]. /// -/// Use [if_group_breaks] or [if_group_fits_on_line] if the fitting and breaking content differs more than just the +/// Use [`if_group_breaks`] or [`if_group_fits_on_line`] if the fitting and breaking content differs more than just the /// indention level. /// /// # Examples @@ -1955,9 +1989,11 @@ pub struct IndentIfGroupBreaks<'a, Context> { impl Format for IndentIfGroupBreaks<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(StartIndentIfGroupBreaks(self.group_id)))?; + f.write_element(FormatElement::Tag(StartIndentIfGroupBreaks(self.group_id))); Arguments::from(&self.content).fmt(f)?; - f.write_element(FormatElement::Tag(EndIndentIfGroupBreaks)) + f.write_element(FormatElement::Tag(EndIndentIfGroupBreaks)); + + Ok(()) } } @@ -1972,7 +2008,7 @@ impl std::fmt::Debug for IndentIfGroupBreaks<'_, Context> { /// Changes the definition of *fits* for `content`. Instead of measuring it in *flat*, measure it with /// all line breaks expanded and test if no line exceeds the line width. The [`FitsExpanded`] acts -/// as a expands boundary similar to best fitting, meaning that a [hard_line_break] will not cause the parent group to expand. +/// as a expands boundary similar to best fitting, meaning that a [`hard_line_break`] will not cause the parent group to expand. /// /// Useful in conjunction with a group with a condition. /// @@ -2034,6 +2070,7 @@ pub struct FitsExpanded<'a, Context> { impl FitsExpanded<'_, Context> { /// Sets a `condition` to when the content should fit in expanded mode. The content uses the regular fits /// definition if the `condition` is not met. + #[must_use] pub fn with_condition(mut self, condition: Option) -> Self { self.condition = condition; self @@ -2044,9 +2081,11 @@ impl Format for FitsExpanded<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { f.write_element(FormatElement::Tag(StartFitsExpanded( tag::FitsExpanded::new().with_condition(self.condition), - )))?; + ))); f.write_fmt(Arguments::from(&self.content))?; - f.write_element(FormatElement::Tag(EndFitsExpanded)) + f.write_element(FormatElement::Tag(EndFitsExpanded)); + + Ok(()) } } @@ -2061,7 +2100,7 @@ impl Format for FormatWith where T: Fn(&mut Formatter) -> FormatResult<()>, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { (self.formatter)(f) } @@ -2207,7 +2246,7 @@ impl Format for FormatOnce where T: FnOnce(&mut Formatter) -> FormatResult<()>, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let formatter = self.formatter.take().expect("Tried to format a `format_once` at least twice. This is not allowed. You may want to use `format_with` or `format.memoized` instead."); @@ -2222,7 +2261,7 @@ impl std::fmt::Debug for FormatOnce { } /// Builder to join together a sequence of content. -/// See [Formatter::join] +/// See [`Formatter::join`] #[must_use = "must eventually call `finish()` on Format builders"] pub struct JoinBuilder<'fmt, 'buf, Separator, Context> { result: FormatResult<()>, @@ -2300,10 +2339,10 @@ pub struct FillBuilder<'fmt, 'buf, Context> { impl<'a, 'buf, Context> FillBuilder<'a, 'buf, Context> { pub(crate) fn new(fmt: &'a mut Formatter<'buf, Context>) -> Self { - let result = fmt.write_element(FormatElement::Tag(StartFill)); + fmt.write_element(FormatElement::Tag(StartFill)); Self { - result, + result: Ok(()), fmt, empty: true, } @@ -2332,14 +2371,15 @@ impl<'a, 'buf, Context> FillBuilder<'a, 'buf, Context> { if self.empty { self.empty = false; } else { - self.fmt.write_element(FormatElement::Tag(StartEntry))?; + self.fmt.write_element(FormatElement::Tag(StartEntry)); separator.fmt(self.fmt)?; - self.fmt.write_element(FormatElement::Tag(EndEntry))?; + self.fmt.write_element(FormatElement::Tag(EndEntry)); } - self.fmt.write_element(FormatElement::Tag(StartEntry))?; + self.fmt.write_element(FormatElement::Tag(StartEntry)); entry.fmt(self.fmt)?; - self.fmt.write_element(FormatElement::Tag(EndEntry)) + self.fmt.write_element(FormatElement::Tag(EndEntry)); + Ok(()) }); self @@ -2347,8 +2387,10 @@ impl<'a, 'buf, Context> FillBuilder<'a, 'buf, Context> { /// Finishes the output and returns any error encountered pub fn finish(&mut self) -> FormatResult<()> { + if self.result.is_ok() { + self.fmt.write_element(FormatElement::Tag(EndFill)); + } self.result - .and_then(|_| self.fmt.write_element(FormatElement::Tag(EndFill))) } } @@ -2357,6 +2399,7 @@ impl<'a, 'buf, Context> FillBuilder<'a, 'buf, Context> { #[derive(Copy, Clone)] pub struct BestFitting<'a, Context> { variants: Arguments<'a, Context>, + mode: BestFittingMode, } impl<'a, Context> BestFitting<'a, Context> { @@ -2367,42 +2410,157 @@ impl<'a, Context> BestFitting<'a, Context> { /// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro. /// /// ## Safety + /// The slice must contain at least two variants. + #[allow(unsafe_code)] pub unsafe fn from_arguments_unchecked(variants: Arguments<'a, Context>) -> Self { assert!( variants.0.len() >= 2, "Requires at least the least expanded and most expanded variants" ); - Self { variants } + Self { + variants, + mode: BestFittingMode::default(), + } + } + + /// Changes the mode used by this best fitting element to determine whether a variant fits. + /// + /// ## Examples + /// + /// ### All Lines + /// + /// ``` + /// use ruff_formatter::{Formatted, LineWidth, format, format_args, SimpleFormatOptions}; + /// use ruff_formatter::prelude::*; + /// + /// # fn main() -> FormatResult<()> { + /// let formatted = format!( + /// SimpleFormatContext::default(), + /// [ + /// best_fitting!( + /// // Everything fits on a single line + /// format_args!( + /// group(&format_args![ + /// text("["), + /// soft_block_indent(&format_args![ + /// text("1,"), + /// soft_line_break_or_space(), + /// text("2,"), + /// soft_line_break_or_space(), + /// text("3"), + /// ]), + /// text("]") + /// ]), + /// space(), + /// text("+"), + /// space(), + /// text("aVeryLongIdentifier") + /// ), + /// + /// // Breaks after `[` and prints each elements on a single line + /// // The group is necessary because the variant, by default is printed in flat mode and a + /// // hard line break indicates that the content doesn't fit. + /// format_args!( + /// text("["), + /// group(&block_indent(&format_args![text("1,"), hard_line_break(), text("2,"), hard_line_break(), text("3")])).should_expand(true), + /// text("]"), + /// space(), + /// text("+"), + /// space(), + /// text("aVeryLongIdentifier") + /// ), + /// + /// // Adds parentheses and indents the body, breaks after the operator + /// format_args!( + /// text("("), + /// block_indent(&format_args![ + /// text("["), + /// block_indent(&format_args![ + /// text("1,"), + /// hard_line_break(), + /// text("2,"), + /// hard_line_break(), + /// text("3"), + /// ]), + /// text("]"), + /// hard_line_break(), + /// text("+"), + /// space(), + /// text("aVeryLongIdentifier") + /// ]), + /// text(")") + /// ) + /// ).with_mode(BestFittingMode::AllLines) + /// ] + /// )?; + /// + /// let document = formatted.into_document(); + /// + /// // Takes the first variant if everything fits on a single line + /// assert_eq!( + /// "[1, 2, 3] + aVeryLongIdentifier", + /// Formatted::new(document.clone(), SimpleFormatContext::default()) + /// .print()? + /// .as_code() + /// ); + /// + /// // It takes the second if the first variant doesn't fit on a single line. The second variant + /// // has some additional line breaks to make sure inner groups don't break + /// assert_eq!( + /// "[\n\t1,\n\t2,\n\t3\n] + aVeryLongIdentifier", + /// Formatted::new(document.clone(), SimpleFormatContext::new(SimpleFormatOptions { line_width: 23.try_into().unwrap(), ..SimpleFormatOptions::default() })) + /// .print()? + /// .as_code() + /// ); + /// + /// // Prints the last option as last resort + /// assert_eq!( + /// "(\n\t[\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n\t+ aVeryLongIdentifier\n)", + /// Formatted::new(document.clone(), SimpleFormatContext::new(SimpleFormatOptions { line_width: 22.try_into().unwrap(), ..SimpleFormatOptions::default() })) + /// .print()? + /// .as_code() + /// ); + /// # Ok(()) + /// # } + /// ``` + #[must_use] + pub fn with_mode(mut self, mode: BestFittingMode) -> Self { + self.mode = mode; + self } } impl Format for BestFitting<'_, Context> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - let mut buffer = VecBuffer::new(f.state_mut()); let variants = self.variants.items(); let mut formatted_variants = Vec::with_capacity(variants.len()); for variant in variants { - buffer.write_element(FormatElement::Tag(StartEntry))?; + let mut buffer = VecBuffer::with_capacity(8, f.state_mut()); + buffer.write_element(FormatElement::Tag(StartEntry)); buffer.write_fmt(Arguments::from(variant))?; - buffer.write_element(FormatElement::Tag(EndEntry))?; + buffer.write_element(FormatElement::Tag(EndEntry)); - formatted_variants.push(buffer.take_vec().into_boxed_slice()); + formatted_variants.push(buffer.into_vec().into_boxed_slice()); } // SAFETY: The constructor guarantees that there are always at least two variants. It's, therefore, // safe to call into the unsafe `from_vec_unchecked` function + #[allow(unsafe_code)] let element = unsafe { FormatElement::BestFitting { variants: format_element::BestFittingVariants::from_vec_unchecked( formatted_variants, ), + mode: self.mode, } }; - f.write_element(element) + f.write_element(element); + + Ok(()) } } diff --git a/crates/ruff_formatter/src/diagnostics.rs b/crates/ruff_formatter/src/diagnostics.rs index 9228975a7e64e..7c9944a562d39 100644 --- a/crates/ruff_formatter/src/diagnostics.rs +++ b/crates/ruff_formatter/src/diagnostics.rs @@ -1,4 +1,5 @@ use crate::prelude::TagKind; +use crate::GroupId; use ruff_text_size::TextRange; use std::error::Error; @@ -86,7 +87,9 @@ pub enum InvalidDocumentError { /// Text /// EndGroup /// ``` - StartTagMissing { kind: TagKind }, + StartTagMissing { + kind: TagKind, + }, /// Expected a specific start tag but instead is: /// - at the end of the document @@ -96,6 +99,10 @@ pub enum InvalidDocumentError { expected_start: TagKind, actual: ActualStart, }, + + UnknownGroupId { + group_id: GroupId, + }, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -148,6 +155,9 @@ impl std::fmt::Display for InvalidDocumentError { } } } + InvalidDocumentError::UnknownGroupId { group_id } => { + std::write!(f, "Encountered unknown group id {group_id:?}. Ensure that the group with the id {group_id:?} exists and that the group is a parent of or comes before the element referring to it.") + } } } } diff --git a/crates/ruff_formatter/src/format_element.rs b/crates/ruff_formatter/src/format_element.rs index 7506c9cb75371..14a15cfaf246d 100644 --- a/crates/ruff_formatter/src/format_element.rs +++ b/crates/ruff_formatter/src/format_element.rs @@ -13,7 +13,7 @@ use ruff_text_size::TextSize; /// Language agnostic IR for formatting source code. /// -/// Use the helper functions like [crate::builders::space], [crate::builders::soft_line_break] etc. defined in this file to create elements. +/// Use the helper functions like [`crate::builders::space`], [`crate::builders::soft_line_break`] etc. defined in this file to create elements. #[derive(Clone, Eq, PartialEq)] pub enum FormatElement { /// A space token, see [crate::builders::space] for documentation. @@ -57,7 +57,10 @@ pub enum FormatElement { /// A list of different variants representing the same content. The printer picks the best fitting content. /// Line breaks inside of a best fitting don't propagate to parent groups. - BestFitting { variants: BestFittingVariants }, + BestFitting { + variants: BestFittingVariants, + mode: BestFittingMode, + }, /// A [Tag] that marks the start/end of some content to which some special formatting is applied. Tag(Tag), @@ -84,13 +87,12 @@ impl std::fmt::Debug for FormatElement { .field(contains_newlines) .finish(), FormatElement::LineSuffixBoundary => write!(fmt, "LineSuffixBoundary"), - FormatElement::BestFitting { variants } => fmt + FormatElement::BestFitting { variants, mode } => fmt .debug_struct("BestFitting") .field("variants", variants) + .field("mode", &mode) .finish(), - FormatElement::Interned(interned) => { - fmt.debug_list().entries(interned.deref()).finish() - } + FormatElement::Interned(interned) => fmt.debug_list().entries(&**interned).finish(), FormatElement::Tag(tag) => fmt.debug_tuple("Tag").field(tag).finish(), FormatElement::SourcePosition(position) => { fmt.debug_tuple("SourcePosition").field(position).finish() @@ -180,7 +182,7 @@ impl Deref for Interned { type Target = [FormatElement]; fn deref(&self) -> &Self::Target { - self.0.deref() + &self.0 } } @@ -217,12 +219,12 @@ pub fn normalize_newlines(text: &str, terminators: [char; N]) -> } impl FormatElement { - /// Returns `true` if self is a [FormatElement::Tag] + /// Returns `true` if self is a [`FormatElement::Tag`] pub const fn is_tag(&self) -> bool { matches!(self, FormatElement::Tag(_)) } - /// Returns `true` if self is a [FormatElement::Tag] and [Tag::is_start] is `true`. + /// Returns `true` if self is a [`FormatElement::Tag`] and [`Tag::is_start`] is `true`. pub const fn is_start_tag(&self) -> bool { match self { FormatElement::Tag(tag) => tag.is_start(), @@ -230,7 +232,7 @@ impl FormatElement { } } - /// Returns `true` if self is a [FormatElement::Tag] and [Tag::is_end] is `true`. + /// Returns `true` if self is a [`FormatElement::Tag`] and [`Tag::is_end`] is `true`. pub const fn is_end_tag(&self) -> bool { match self { FormatElement::Tag(tag) => tag.is_end(), @@ -297,6 +299,29 @@ impl FormatElements for FormatElement { } } +/// Mode used to determine if any variant (except the most expanded) fits for [`BestFittingVariants`]. +#[repr(u8)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] +pub enum BestFittingMode { + /// The variant fits if the content up to the first hard or a soft line break inside a [`Group`] with + /// [`PrintMode::Expanded`] fits on the line. The default mode. + /// + /// [`Group`]: tag::Group + #[default] + FirstLine, + + /// A variant fits if all lines fit into the configured print width. A line ends if by any + /// hard or a soft line break inside a [`Group`] with [`PrintMode::Expanded`]. + /// The content doesn't fit if there's any hard line break outside a [`Group`] with [`PrintMode::Expanded`] + /// (a hard line break in content that should be considered in [`PrintMode::Flat`]. + /// + /// Use this mode with caution as it requires measuring all content of the variant which is more + /// expensive than using [`BestFittingMode::FirstLine`]. + /// + /// [`Group`]: tag::Group + AllLines, +} + /// The different variants for this element. /// The first element is the one that takes up the most space horizontally (the most flat), /// The last element takes up the least space horizontally (but most horizontal space). @@ -313,6 +338,7 @@ impl BestFittingVariants { /// ## Safety /// The slice must contain at least two variants. #[doc(hidden)] + #[allow(unsafe_code)] pub unsafe fn from_vec_unchecked(variants: Vec>) -> Self { debug_assert!( variants.len() >= 2, @@ -359,9 +385,9 @@ impl<'a> IntoIterator for &'a BestFittingVariants { } pub trait FormatElements { - /// Returns true if this [FormatElement] is guaranteed to break across multiple lines by the printer. + /// Returns true if this [`FormatElement`] is guaranteed to break across multiple lines by the printer. /// This is the case if this format element recursively contains a: - /// - [crate::builders::empty_line] or [crate::builders::hard_line_break] + /// - [`crate::builders::empty_line`] or [`crate::builders::hard_line_break`] /// - A token containing '\n' /// /// Use this with caution, this is only a heuristic and the printer may print the element over multiple diff --git a/crates/ruff_formatter/src/format_element/document.rs b/crates/ruff_formatter/src/format_element/document.rs index e4dbdb8d4df01..42bc2b1f39961 100644 --- a/crates/ruff_formatter/src/format_element/document.rs +++ b/crates/ruff_formatter/src/format_element/document.rs @@ -21,9 +21,9 @@ pub struct Document { impl Document { /// Sets [`expand`](tag::Group::expand) to [`GroupMode::Propagated`] if the group contains any of: - /// - a group with [`expand`](tag::Group::expand) set to [GroupMode::Propagated] or [GroupMode::Expand]. - /// - a non-soft [line break](FormatElement::Line) with mode [LineMode::Hard], [LineMode::Empty], or [LineMode::Literal]. - /// - a [FormatElement::ExpandParent] + /// - a group with [`expand`](tag::Group::expand) set to [`GroupMode::Propagated`] or [`GroupMode::Expand`]. + /// - a non-soft [line break](FormatElement::Line) with mode [`LineMode::Hard`], [`LineMode::Empty`], or [`LineMode::Literal`]. + /// - a [`FormatElement::ExpandParent`] /// /// [`BestFitting`] elements act as expand boundaries, meaning that the fact that a /// [`BestFitting`]'s content expands is not propagated past the [`BestFitting`] element. @@ -71,16 +71,17 @@ impl Document { Some(Enclosing::ConditionalGroup(group)) => !group.mode().is_flat(), _ => false, }, - FormatElement::Interned(interned) => match checked_interned.get(interned) { - Some(interned_expands) => *interned_expands, - None => { + FormatElement::Interned(interned) => { + if let Some(interned_expands) = checked_interned.get(interned) { + *interned_expands + } else { let interned_expands = propagate_expands(interned, enclosing, checked_interned); checked_interned.insert(interned, interned_expands); interned_expands } - }, - FormatElement::BestFitting { variants } => { + } + FormatElement::BestFitting { variants, mode: _ } => { enclosing.push(Enclosing::BestFitting); for variant in variants { @@ -114,15 +115,19 @@ impl Document { if element_expands { expands = true; - expand_parent(enclosing) + expand_parent(enclosing); } } expands } - let mut enclosing: Vec = Vec::new(); - let mut interned: FxHashMap<&Interned, bool> = FxHashMap::default(); + let mut enclosing = Vec::with_capacity(if self.is_empty() { + 0 + } else { + self.len().ilog2() as usize + }); + let mut interned = FxHashMap::default(); propagate_expands(self, &mut enclosing, &mut interned); } @@ -226,6 +231,7 @@ impl FormatOptions for IrFormatOptions { impl Format> for &[FormatElement] { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + #[allow(clippy::enum_glob_use)] use Tag::*; write!(f, [ContentArrayStart])?; @@ -245,20 +251,11 @@ impl Format> for &[FormatElement] { first_element = false; match element { - element @ FormatElement::Space - | element @ FormatElement::StaticText { .. } - | element @ FormatElement::DynamicText { .. } - | element @ FormatElement::SourceCodeSlice { .. } => { - if !in_text { - write!(f, [text("\"")])?; - } - - in_text = true; - - fn write_escaped( - element: &FormatElement, - f: &mut Formatter, - ) -> FormatResult<()> { + element @ (FormatElement::Space + | FormatElement::StaticText { .. } + | FormatElement::DynamicText { .. } + | FormatElement::SourceCodeSlice { .. }) => { + fn write_escaped(element: &FormatElement, f: &mut Formatter) { let text = match element { FormatElement::StaticText { text } => text, FormatElement::DynamicText { text } => text.as_ref(), @@ -271,23 +268,29 @@ impl Format> for &[FormatElement] { if text.contains('"') { f.write_element(FormatElement::DynamicText { text: text.replace('"', r#"\""#).into(), - }) + }); } else { - f.write_element(element.clone()) + f.write_element(element.clone()); } } + if !in_text { + write!(f, [text("\"")])?; + } + + in_text = true; + match element { FormatElement::Space => { write!(f, [text(" ")])?; } element if element.is_text() => { - write_escaped(element, f)?; + write_escaped(element, f); } _ => unreachable!(), } - let is_next_text = iter.peek().map_or(false, |e| e.is_text() || e.is_space()); + let is_next_text = iter.peek().is_some_and(|e| e.is_text() || e.is_space()); if !is_next_text { write!(f, [text("\"")])?; @@ -317,7 +320,7 @@ impl Format> for &[FormatElement] { write!( f, [dynamic_text( - &std::format!("source_position({:?})", position), + &std::format!("source_position({position:?})"), None )] )?; @@ -327,23 +330,29 @@ impl Format> for &[FormatElement] { write!(f, [text("line_suffix_boundary")])?; } - FormatElement::BestFitting { variants } => { + FormatElement::BestFitting { variants, mode } => { write!(f, [text("best_fitting([")])?; f.write_elements([ FormatElement::Tag(StartIndent), FormatElement::Line(LineMode::Hard), - ])?; + ]); for variant in variants { - write!(f, [variant.deref(), hard_line_break()])?; + write!(f, [&**variant, hard_line_break()])?; } f.write_elements([ FormatElement::Tag(EndIndent), FormatElement::Line(LineMode::Hard), - ])?; + ]); + + write!(f, [text("]")])?; + + if *mode != BestFittingMode::FirstLine { + write!(f, [dynamic_text(&std::format!(", mode: {mode:?}"), None),])?; + } - write!(f, [text("])")])?; + write!(f, [text(")")])?; } FormatElement::Interned(interned) => { @@ -359,7 +368,7 @@ impl Format> for &[FormatElement] { [ dynamic_text(&std::format!(""), None), space(), - &interned.deref(), + &&**interned, ] )?; } @@ -621,7 +630,7 @@ struct ContentArrayStart; impl Format> for ContentArrayStart { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - use Tag::*; + use Tag::{StartGroup, StartIndent}; write!(f, [text("[")])?; @@ -629,7 +638,9 @@ impl Format> for ContentArrayStart { FormatElement::Tag(StartGroup(tag::Group::new())), FormatElement::Tag(StartIndent), FormatElement::Line(LineMode::Soft), - ]) + ]); + + Ok(()) } } @@ -637,12 +648,12 @@ struct ContentArrayEnd; impl Format> for ContentArrayEnd { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - use Tag::*; + use Tag::{EndGroup, EndIndent}; f.write_elements([ FormatElement::Tag(EndIndent), FormatElement::Line(LineMode::Soft), FormatElement::Tag(EndGroup), - ])?; + ]); write!(f, [text("]")]) } @@ -650,18 +661,17 @@ impl Format> for ContentArrayEnd { impl FormatElements for [FormatElement] { fn will_break(&self) -> bool { - use Tag::*; let mut ignore_depth = 0usize; for element in self { match element { // Line suffix // Ignore if any of its content breaks - FormatElement::Tag(StartLineSuffix) => { + FormatElement::Tag(Tag::StartLineSuffix | Tag::StartFitsExpanded(_)) => { ignore_depth += 1; } - FormatElement::Tag(EndLineSuffix) => { - ignore_depth -= 1; + FormatElement::Tag(Tag::EndLineSuffix | Tag::EndFitsExpanded) => { + ignore_depth = ignore_depth.saturating_sub(1); } FormatElement::Interned(interned) if ignore_depth == 0 => { if interned.will_break() { @@ -683,13 +693,10 @@ impl FormatElements for [FormatElement] { fn has_label(&self, expected: LabelId) -> bool { self.first() - .map_or(false, |element| element.has_label(expected)) + .is_some_and(|element| element.has_label(expected)) } fn start_tag(&self, kind: TagKind) -> Option<&Tag> { - // Assert that the document ends at a tag with the specified kind; - let _ = self.end_tag(kind)?; - fn traverse_slice<'a>( slice: &'a [FormatElement], kind: TagKind, @@ -704,9 +711,8 @@ impl FormatElements for [FormatElement] { return None; } else if *depth == 1 { return Some(tag); - } else { - *depth -= 1; } + *depth -= 1; } else { *depth += 1; } @@ -731,6 +737,8 @@ impl FormatElements for [FormatElement] { None } + // Assert that the document ends at a tag with the specified kind; + let _ = self.end_tag(kind)?; let mut depth = 0usize; diff --git a/crates/ruff_formatter/src/format_element/tag.rs b/crates/ruff_formatter/src/format_element/tag.rs index f586cc8b1c9c6..91609b82c4800 100644 --- a/crates/ruff_formatter/src/format_element/tag.rs +++ b/crates/ruff_formatter/src/format_element/tag.rs @@ -109,6 +109,7 @@ impl Tag { } pub const fn kind(&self) -> TagKind { + #[allow(clippy::enum_glob_use)] use Tag::*; match self { @@ -180,13 +181,14 @@ impl FitsExpanded { Self::default() } + #[must_use] pub fn with_condition(mut self, condition: Option) -> Self { self.condition = condition; self } pub fn propagate_expand(&self) { - self.propagate_expand.set(true) + self.propagate_expand.set(true); } } @@ -204,11 +206,13 @@ impl Group { } } + #[must_use] pub fn with_id(mut self, id: Option) -> Self { self.id = id; self } + #[must_use] pub fn with_mode(mut self, mode: GroupMode) -> Self { self.mode = Cell::new(mode); self @@ -220,7 +224,7 @@ impl Group { pub fn propagate_expand(&self) { if self.mode.get() == GroupMode::Flat { - self.mode.set(GroupMode::Propagated) + self.mode.set(GroupMode::Propagated); } } @@ -248,7 +252,7 @@ impl ConditionalGroup { } pub fn propagate_expand(&self) { - self.mode.set(GroupMode::Propagated) + self.mode.set(GroupMode::Propagated); } pub fn mode(&self) -> GroupMode { @@ -312,6 +316,7 @@ impl Condition { } } + #[must_use] pub fn with_group_id(mut self, id: Option) -> Self { self.group_id = id; self @@ -350,6 +355,7 @@ impl PartialEq for LabelId { } impl LabelId { + #[allow(clippy::needless_pass_by_value)] pub fn of(label: T) -> Self { Self { value: label.value(), diff --git a/crates/ruff_formatter/src/format_extensions.rs b/crates/ruff_formatter/src/format_extensions.rs index cde30df58a4ad..b1fb33d6b6cad 100644 --- a/crates/ruff_formatter/src/format_extensions.rs +++ b/crates/ruff_formatter/src/format_extensions.rs @@ -3,7 +3,6 @@ use crate::prelude::*; use std::cell::RefCell; use std::marker::PhantomData; -use std::ops::Deref; use crate::Buffer; @@ -149,7 +148,7 @@ where .get_or_insert_with(|| f.intern(&self.inner)); match result.as_ref() { - Ok(Some(FormatElement::Interned(interned))) => Ok(interned.deref()), + Ok(Some(FormatElement::Interned(interned))) => Ok(&**interned), Ok(Some(other)) => Ok(std::slice::from_ref(other)), Ok(None) => Ok(&[]), Err(error) => Err(*error), @@ -167,7 +166,7 @@ where match result { Ok(Some(elements)) => { - f.write_element(elements.clone())?; + f.write_element(elements.clone()); Ok(()) } diff --git a/crates/ruff_formatter/src/formatter.rs b/crates/ruff_formatter/src/formatter.rs index 2f3201090207c..9a4363580756c 100644 --- a/crates/ruff_formatter/src/formatter.rs +++ b/crates/ruff_formatter/src/formatter.rs @@ -35,7 +35,7 @@ impl<'buf, Context> Formatter<'buf, Context> { } /// Creates a new group id that is unique to this document. The passed debug name is used in the - /// [std::fmt::Debug] of the document if this is a debug build. + /// [`std::fmt::Debug`] of the document if this is a debug build. /// The name is unused for production builds and has no meaning on the equality of two group ids. pub fn group_id(&self, debug_name: &'static str) -> GroupId { self.state().group_id(debug_name) @@ -108,7 +108,7 @@ impl<'buf, Context> Formatter<'buf, Context> { JoinBuilder::with_separator(self, joiner) } - /// Concatenates a list of [crate::Format] objects with spaces and line breaks to fit + /// Concatenates a list of [`crate::Format`] objects with spaces and line breaks to fit /// them on as few lines as possible. Each element introduces a conceptual group. The printer /// first tries to print the item in flat mode but then prints it in expanded mode if it doesn't fit. /// @@ -205,16 +205,16 @@ where impl Buffer for Formatter<'_, Context> { type Context = Context; - #[inline(always)] - fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - self.buffer.write_element(element) + #[inline] + fn write_element(&mut self, element: FormatElement) { + self.buffer.write_element(element); } fn elements(&self) -> &[FormatElement] { self.buffer.elements() } - #[inline(always)] + #[inline] fn write_fmt(&mut self, arguments: Arguments) -> FormatResult<()> { for argument in arguments.items() { argument.format(self)?; @@ -235,7 +235,7 @@ impl Buffer for Formatter<'_, Context> { } fn restore_snapshot(&mut self, snapshot: BufferSnapshot) { - self.buffer.restore_snapshot(snapshot) + self.buffer.restore_snapshot(snapshot); } } diff --git a/crates/ruff_formatter/src/group_id.rs b/crates/ruff_formatter/src/group_id.rs index 8f06ae8e3788f..94b36fa071c37 100644 --- a/crates/ruff_formatter/src/group_id.rs +++ b/crates/ruff_formatter/src/group_id.rs @@ -1,9 +1,11 @@ use std::num::NonZeroU32; use std::sync::atomic::{AtomicU32, Ordering}; +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Eq, PartialEq, Hash)] pub struct DebugGroupId { value: NonZeroU32, + #[cfg_attr(feature = "serde", serde(skip))] name: &'static str, } @@ -25,9 +27,10 @@ impl std::fmt::Debug for DebugGroupId { /// Unique identification for a group. /// -/// See [crate::Formatter::group_id] on how to get a unique id. +/// See [`crate::Formatter::group_id`] on how to get a unique id. #[repr(transparent)] #[derive(Clone, Copy, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ReleaseGroupId { value: NonZeroU32, } diff --git a/crates/ruff_formatter/src/lib.rs b/crates/ruff_formatter/src/lib.rs index 9034e271d9ad5..4f9f83827091a 100644 --- a/crates/ruff_formatter/src/lib.rs +++ b/crates/ruff_formatter/src/lib.rs @@ -1,15 +1,15 @@ //! Infrastructure for code formatting //! -//! This module defines [FormatElement], an IR to format code documents and provides a mean to print +//! This module defines [`FormatElement`], an IR to format code documents and provides a means to print //! such a document to a string. Objects that know how to format themselves implement the [Format] trait. //! //! ## Formatting Traits //! -//! * [Format]: Implemented by objects that can be formatted. -//! * [FormatRule]: Rule that knows how to format an object of another type. Necessary in the situation where +//! * [`Format`]: Implemented by objects that can be formatted. +//! * [`FormatRule`]: Rule that knows how to format an object of another type. Useful in the situation where //! it's necessary to implement [Format] on an object from another crate. This module defines the -//! [FormatRefWithRule] and [FormatOwnedWithRule] structs to pass an item with its corresponding rule. -//! * [FormatWithRule] implemented by objects that know how to format another type. Useful for implementing +//! [`FormatRefWithRule`] and [`FormatOwnedWithRule`] structs to pass an item with its corresponding rule. +//! * [`FormatWithRule`] implemented by objects that know how to format another type. Useful for implementing //! some reusable formatting logic inside of this module if the type itself doesn't implement [Format] //! //! ## Formatting Macros @@ -19,9 +19,6 @@ //! * [`format_args!`]: Concatenates a sequence of Format objects. //! * [`write!`]: Writes a sequence of formatable objects into an output buffer. -#![allow(clippy::pedantic, unsafe_code)] -#![deny(rustdoc::broken_intra_doc_links)] - mod arguments; mod buffer; mod builders; @@ -45,8 +42,7 @@ use crate::format_element::document::Document; use crate::printer::{Printer, PrinterOptions}; pub use arguments::{Argument, Arguments}; pub use buffer::{ - Buffer, BufferExtensions, BufferSnapshot, Inspect, PreambleBuffer, RemoveSoftLinesBuffer, - VecBuffer, + Buffer, BufferExtensions, BufferSnapshot, Inspect, RemoveSoftLinesBuffer, VecBuffer, }; pub use builders::BestFitting; pub use source_code::{SourceCode, SourceCodeSlice}; @@ -73,12 +69,12 @@ pub enum IndentStyle { impl IndentStyle { pub const DEFAULT_SPACES: u8 = 2; - /// Returns `true` if this is an [IndentStyle::Tab]. + /// Returns `true` if this is an [`IndentStyle::Tab`]. pub const fn is_tab(&self) -> bool { matches!(self, IndentStyle::Tab) } - /// Returns `true` if this is an [IndentStyle::Space]. + /// Returns `true` if this is an [`IndentStyle::Space`]. pub const fn is_space(&self) -> bool { matches!(self, IndentStyle::Space(_)) } @@ -92,7 +88,13 @@ impl FromStr for IndentStyle { "tab" | "Tabs" => Ok(Self::Tab), "space" | "Spaces" => Ok(Self::Space(IndentStyle::DEFAULT_SPACES)), // TODO: replace this error with a diagnostic - _ => Err("Value not supported for IndentStyle"), + v => { + let v = v.strip_prefix("Spaces, size: ").unwrap_or(v); + + u8::from_str(v) + .map(Self::Space) + .map_err(|_| "Value not supported for IndentStyle") + } } } } @@ -115,10 +117,10 @@ impl std::fmt::Display for IndentStyle { pub struct LineWidth(u16); impl LineWidth { - /// Maximum allowed value for a valid [LineWidth] + /// Maximum allowed value for a valid [`LineWidth`] pub const MAX: u16 = 320; - /// Return the numeric value for this [LineWidth] + /// Return the numeric value for this [`LineWidth`] pub fn value(&self) -> u16 { self.0 } @@ -130,7 +132,7 @@ impl Default for LineWidth { } } -/// Error type returned when parsing a [LineWidth] from a string fails +/// Error type returned when parsing a [`LineWidth`] from a string fails pub enum ParseLineWidthError { /// The string could not be parsed as a valid [u16] ParseError(ParseIntError), @@ -163,7 +165,7 @@ impl FromStr for LineWidth { } } -/// Error type returned when converting a u16 to a [LineWidth] fails +/// Error type returned when converting a u16 to a [`LineWidth`] fails #[derive(Clone, Copy, Debug)] pub struct LineWidthFromIntError(pub u16); @@ -232,6 +234,7 @@ impl SimpleFormatContext { } } + #[must_use] pub fn with_source_code(mut self, code: &str) -> Self { self.source_code = String::from(code); self @@ -315,20 +318,20 @@ where Context: FormatContext, { pub fn print(&self) -> PrintResult { - let source_code = self.context.source_code(); - let print_options = self.context.options().as_print_options(); - let printed = Printer::new(source_code, print_options).print(&self.document)?; - - Ok(printed) + let printer = self.create_printer(); + printer.print(&self.document) } pub fn print_with_indent(&self, indent: u16) -> PrintResult { + let printer = self.create_printer(); + printer.print_with_indent(&self.document, indent) + } + + fn create_printer(&self) -> Printer { let source_code = self.context.source_code(); let print_options = self.context.options().as_print_options(); - let printed = - Printer::new(source_code, print_options).print_with_indent(&self.document, indent)?; - Ok(printed) + Printer::new(source_code, print_options) } } @@ -384,20 +387,20 @@ impl Printed { self.range } - /// Returns a list of [SourceMarker] mapping byte positions + /// Returns a list of [`SourceMarker`] mapping byte positions /// in the output string to the input source code. /// It's not guaranteed that the markers are sorted by source position. pub fn sourcemap(&self) -> &[SourceMarker] { &self.sourcemap } - /// Returns a list of [SourceMarker] mapping byte positions + /// Returns a list of [`SourceMarker`] mapping byte positions /// in the output string to the input source code, consuming the result pub fn into_sourcemap(self) -> Vec { self.sourcemap } - /// Takes the list of [SourceMarker] mapping byte positions in the output string + /// Takes the list of [`SourceMarker`] mapping byte positions in the output string /// to the input source code. pub fn take_sourcemap(&mut self) -> Vec { std::mem::take(&mut self.sourcemap) @@ -435,7 +438,7 @@ impl Printed { pub type FormatResult = Result; /// Formatting trait for types that can create a formatted representation. The `ruff_formatter` equivalent -/// to [std::fmt::Display]. +/// to [`std::fmt::Display`]. /// /// ## Example /// Implementing `Format` for a custom struct @@ -474,7 +477,7 @@ impl Format for &T where T: ?Sized + Format, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { Format::fmt(&**self, f) } @@ -484,7 +487,7 @@ impl Format for &mut T where T: ?Sized + Format, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { Format::fmt(&**self, f) } @@ -512,7 +515,7 @@ impl Format for () { /// Rule that knows how to format an object of type `T`. /// -/// Implementing [Format] on the object itself is preferred over implementing [FormatRule] but +/// Implementing [Format] on the object itself is preferred over implementing [`FormatRule`] but /// this isn't possible inside of a dependent crate for external type. /// /// For example, the `ruff_js_formatter` crate isn't able to implement [Format] on `JsIfStatement` @@ -529,6 +532,7 @@ pub trait FormatRuleWithOptions: FormatRule { type Options; /// Returns a new rule that uses the given options to format an object. + #[must_use] fn with_options(self, options: Self::Options) -> Self; } @@ -541,9 +545,9 @@ pub trait FormatRuleWithOptions: FormatRule { /// /// ## Examples /// -/// This can be useful if you want to format a `SyntaxNode` inside ruff_formatter.. `SyntaxNode` doesn't implement [Format] +/// This can be useful if you want to format a `SyntaxNode` inside `ruff_formatter`.. `SyntaxNode` doesn't implement [Format] /// itself but the language specific crate implements `AsFormat` and `IntoFormat` for it and the returned [Format] -/// implement [FormatWithRule]. +/// implement [`FormatWithRule`]. /// /// ```ignore /// use ruff_formatter::prelude::*; @@ -591,6 +595,7 @@ impl FormatRefWithRule<'_, T, R, C> where R: FormatRuleWithOptions, { + #[must_use] pub fn with_options(mut self, options: O) -> Self { self.rule = self.rule.with_options(options); self @@ -612,7 +617,7 @@ impl Format for FormatRefWithRule<'_, T, R, C> where R: FormatRule, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { self.rule.fmt(self.item, f) } @@ -641,6 +646,7 @@ where } } + #[must_use] pub fn with_item(mut self, item: T) -> Self { self.item = item; self @@ -655,7 +661,7 @@ impl Format for FormatOwnedWithRule where R: FormatRule, { - #[inline(always)] + #[inline] fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { self.rule.fmt(&self.item, f) } @@ -665,6 +671,7 @@ impl FormatOwnedWithRule where R: FormatRuleWithOptions, { + #[must_use] pub fn with_options(mut self, options: O) -> Self { self.rule = self.rule.with_options(options); self @@ -723,7 +730,7 @@ where /// # Ok(()) /// # } /// ``` -#[inline(always)] +#[inline] pub fn write( output: &mut dyn Buffer, args: Arguments, @@ -771,8 +778,13 @@ pub fn format( where Context: FormatContext, { + let source_length = context.source_code().as_str().len(); + // Use a simple heuristic to guess the number of expected format elements. + // See [#6612](https://github.com/astral-sh/ruff/pull/6612) for more details on how the formula was determined. Changes to our formatter, or supporting + // more languages may require fine tuning the formula. + let estimated_buffer_size = source_length / 2; let mut state = FormatState::new(context); - let mut buffer = VecBuffer::with_capacity(arguments.items().len(), &mut state); + let mut buffer = VecBuffer::with_capacity(estimated_buffer_size, &mut state); buffer.write_fmt(arguments)?; @@ -784,9 +796,9 @@ where /// This structure stores the state that is relevant for the formatting of the whole document. /// -/// This structure is different from [crate::Formatter] in that the formatting infrastructure -/// creates a new [crate::Formatter] for every [crate::write!] call, whereas this structure stays alive -/// for the whole process of formatting a root with [crate::format!]. +/// This structure is different from [`crate::Formatter`] in that the formatting infrastructure +/// creates a new [`crate::Formatter`] for every [`crate::write`!] call, whereas this structure stays alive +/// for the whole process of formatting a root with [`crate::format`!]. pub struct FormatState { context: Context, @@ -809,7 +821,7 @@ impl FormatState { pub fn new(context: Context) -> Self { Self { context, - group_id_builder: Default::default(), + group_id_builder: UniqueGroupIdBuilder::default(), } } @@ -828,7 +840,7 @@ impl FormatState { } /// Creates a new group id that is unique to this document. The passed debug name is used in the - /// [std::fmt::Debug] of the document if this is a debug build. + /// [`std::fmt::Debug`] of the document if this is a debug build. /// The name is unused for production builds and has no meaning on the equality of two group ids. pub fn group_id(&self, debug_name: &'static str) -> GroupId { self.group_id_builder.group_id(debug_name) diff --git a/crates/ruff_formatter/src/macros.rs b/crates/ruff_formatter/src/macros.rs index 4f5bcdf0508d6..2e6b28bf23545 100644 --- a/crates/ruff_formatter/src/macros.rs +++ b/crates/ruff_formatter/src/macros.rs @@ -1,9 +1,9 @@ /// Constructs the parameters for other formatting macros. /// -/// This macro functions by taking a list of objects implementing [crate::Format]. It canonicalize the +/// This macro functions by taking a list of objects implementing [`crate::Format`]. It will canonicalize the /// arguments into a single type. /// -/// This macro produces a value of type [crate::Arguments]. This value can be passed to +/// This macro produces a value of type [`crate::Arguments`]. This value can be passed to /// the macros within [crate]. All other formatting macros ([`format!`](crate::format!), /// [`write!`](crate::write!)) are proxied through this one. This macro avoids heap allocations. /// @@ -41,7 +41,7 @@ macro_rules! format_args { /// /// This macro accepts a 'buffer' and a list of format arguments. Each argument will be formatted /// and the result will be passed to the buffer. The writer may be any value with a `write_fmt` method; -/// generally this comes from an implementation of the [crate::Buffer] trait. +/// generally this comes from an implementation of the [`crate::Buffer`] trait. /// /// # Examples /// @@ -116,8 +116,8 @@ macro_rules! dbg_write { /// Creates the Format IR for a value. /// -/// The first argument `format!` receives is the [crate::FormatContext] that specify how elements must be formatted. -/// Additional parameters passed get formatted by using their [crate::Format] implementation. +/// The first argument `format!` receives is the [`crate::FormatContext`] that specify how elements must be formatted. +/// Additional parameters passed get formatted by using their [`crate::Format`] implementation. /// /// /// ## Examples @@ -314,13 +314,13 @@ macro_rules! format { /// ## Behavior /// This IR is similar to Prettier's `conditionalGroup`. The printer measures each variant, except the [`MostExpanded`], in [`Flat`] mode /// to find the first variant that fits and prints this variant in [`Flat`] mode. If no variant fits, then -/// the printer falls back to printing the [`MostExpanded`] variant in `[`Expanded`] mode. +/// the printer falls back to printing the [`MostExpanded`] variant in [`Expanded`] mode. /// /// The definition of *fits* differs to groups in that the printer only tests if it is possible to print /// the content up to the first non-soft line break without exceeding the configured print width. /// This definition differs from groups as that non-soft line breaks make group expand. /// -/// [crate::BestFitting] acts as a "break" boundary, meaning that it is considered to fit +/// [`crate::BestFitting`] acts as a "break" boundary, meaning that it is considered to fit /// /// /// [`Flat`]: crate::format_element::PrintMode::Flat @@ -329,6 +329,7 @@ macro_rules! format { #[macro_export] macro_rules! best_fitting { ($least_expanded:expr, $($tail:expr),+ $(,)?) => {{ + #[allow(unsafe_code)] unsafe { $crate::BestFitting::from_arguments_unchecked($crate::format_args!($least_expanded, $($tail),+)) } diff --git a/crates/ruff_formatter/src/printer/call_stack.rs b/crates/ruff_formatter/src/printer/call_stack.rs index a262f210a7ca9..858510ae7f03b 100644 --- a/crates/ruff_formatter/src/printer/call_stack.rs +++ b/crates/ruff_formatter/src/printer/call_stack.rs @@ -20,10 +20,10 @@ pub(super) struct StackFrame { /// Stores arguments passed to `print_element` call, holding the state specific to printing an element. /// E.g. the `indent` depends on the token the Printer's currently processing. That's why -/// it must be stored outside of the [PrinterState] that stores the state common to all elements. +/// it must be stored outside of the [`PrinterState`] that stores the state common to all elements. /// /// The state is passed by value, which is why it's important that it isn't storing any heavy -/// data structures. Such structures should be stored on the [PrinterState] instead. +/// data structures. Such structures should be stored on the [`PrinterState`] instead. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub(super) struct PrintElementArgs { indent: Indention, @@ -39,15 +39,15 @@ impl PrintElementArgs { } } - pub(super) fn mode(&self) -> PrintMode { + pub(super) fn mode(self) -> PrintMode { self.mode } - pub(super) fn measure_mode(&self) -> MeasureMode { + pub(super) fn measure_mode(self) -> MeasureMode { self.measure_mode } - pub(super) fn indention(&self) -> Indention { + pub(super) fn indention(self) -> Indention { self.indent } @@ -92,9 +92,9 @@ impl Default for PrintElementArgs { } } -/// Call stack that stores the [PrintElementCallArgs]. +/// Call stack that stores the [`PrintElementCallArgs`]. /// -/// New [PrintElementCallArgs] are pushed onto the stack for every [`start`](Tag::is_start) [`Tag`](FormatElement::Tag) +/// New [`PrintElementCallArgs`] are pushed onto the stack for every [`start`](Tag::is_start) [`Tag`](FormatElement::Tag) /// and popped when reaching the corresponding [`end`](Tag::is_end) [`Tag`](FormatElement::Tag). pub(super) trait CallStack { type Stack: Stack + Debug; @@ -158,7 +158,7 @@ pub(super) trait CallStack { } } - /// Returns the [PrintElementArgs] for the current stack frame. + /// Returns the [`PrintElementArgs`] for the current stack frame. fn top(&self) -> PrintElementArgs { self.stack() .top() @@ -166,7 +166,7 @@ pub(super) trait CallStack { .args } - /// Returns the [TagKind] of the current stack frame or [None] if this is the root stack frame. + /// Returns the [`TagKind`] of the current stack frame or [None] if this is the root stack frame. fn top_kind(&self) -> Option { match self .stack() @@ -179,16 +179,16 @@ pub(super) trait CallStack { } } - /// Creates a new stack frame for a [FormatElement::Tag] of `kind` with `args` as the call arguments. + /// Creates a new stack frame for a [`FormatElement::Tag`] of `kind` with `args` as the call arguments. fn push(&mut self, kind: TagKind, args: PrintElementArgs) { self.stack_mut().push(StackFrame { kind: StackFrameKind::Tag(kind), args, - }) + }); } } -/// Call stack used for printing the [FormatElement]s +/// Call stack used for printing the [`FormatElement`]s #[derive(Debug, Clone)] pub(super) struct PrintCallStack(Vec); @@ -215,7 +215,7 @@ impl CallStack for PrintCallStack { /// Call stack used for measuring if some content fits on the line. /// -/// The stack is a view on top of the [PrintCallStack] because the stack frames are still necessary for printing. +/// The stack is a view on top of the [`PrintCallStack`] because the stack frames are still necessary for printing. #[must_use] pub(super) struct FitsCallStack<'print> { stack: StackedStack<'print, StackFrame>, diff --git a/crates/ruff_formatter/src/printer/mod.rs b/crates/ruff_formatter/src/printer/mod.rs index df74c7ae36bd5..57e6d1a010ba4 100644 --- a/crates/ruff_formatter/src/printer/mod.rs +++ b/crates/ruff_formatter/src/printer/mod.rs @@ -6,7 +6,7 @@ mod stack; use crate::format_element::document::Document; use crate::format_element::tag::{Condition, GroupMode}; -use crate::format_element::{BestFittingVariants, LineMode, PrintMode}; +use crate::format_element::{BestFittingMode, BestFittingVariants, LineMode, PrintMode}; use crate::prelude::tag; use crate::prelude::tag::{DedentMode, Tag, TagKind, VerbatimKind}; use crate::printer::call_stack::{ @@ -40,7 +40,7 @@ impl<'a> Printer<'a> { Self { source_code, options, - state: PrinterState::default(), + state: PrinterState::with_capacity(source_code.as_str().len()), } } @@ -60,11 +60,13 @@ impl<'a> Printer<'a> { let mut stack = PrintCallStack::new(PrintElementArgs::new(Indention::Level(indent))); let mut queue: PrintQueue<'a> = PrintQueue::new(document.as_ref()); - while let Some(element) = queue.pop() { - self.print_element(&mut stack, &mut queue, element)?; - - if queue.is_empty() { - self.flush_line_suffixes(&mut queue, &mut stack, None); + loop { + if let Some(element) = queue.pop() { + self.print_element(&mut stack, &mut queue, element)?; + } else { + if !self.flush_line_suffixes(&mut queue, &mut stack, None) { + break; + } } } @@ -84,6 +86,7 @@ impl<'a> Printer<'a> { queue: &mut PrintQueue<'a>, element: &'a FormatElement, ) -> PrintResult<()> { + #[allow(clippy::enum_glob_use)] use Tag::*; let args = stack.top(); @@ -94,7 +97,7 @@ impl<'a> Printer<'a> { FormatElement::DynamicText { text } => self.print_text(text, None), FormatElement::SourceCodeSlice { slice, .. } => { let text = slice.text(self.source_code); - self.print_text(text, Some(slice.range())) + self.print_text(text, Some(slice.range())); } FormatElement::Line(line_mode) => { if args.mode().is_flat() @@ -134,8 +137,8 @@ impl<'a> Printer<'a> { self.flush_line_suffixes(queue, stack, Some(HARD_BREAK)); } - FormatElement::BestFitting { variants } => { - self.print_best_fitting(variants, queue, stack)?; + FormatElement::BestFitting { variants, mode } => { + self.print_best_fitting(variants, *mode, queue, stack)?; } FormatElement::Interned(content) => { @@ -143,23 +146,40 @@ impl<'a> Printer<'a> { } FormatElement::Tag(StartGroup(group)) => { - let print_mode = - self.print_group(TagKind::Group, group.mode(), args, queue, stack)?; + let print_mode = match group.mode() { + GroupMode::Expand | GroupMode::Propagated => PrintMode::Expanded, + GroupMode::Flat => { + self.flat_group_print_mode(TagKind::Group, group.id(), args, queue, stack)? + } + }; if let Some(id) = group.id() { self.state.group_modes.insert_print_mode(id, print_mode); } + + stack.push(TagKind::Group, args.with_print_mode(print_mode)); } FormatElement::Tag(StartConditionalGroup(group)) => { let condition = group.condition(); let expected_mode = match condition.group_id { None => args.mode(), - Some(id) => self.state.group_modes.unwrap_print_mode(id, element), + Some(id) => self.state.group_modes.get_print_mode(id)?, }; if expected_mode == condition.mode { - self.print_group(TagKind::ConditionalGroup, group.mode(), args, queue, stack)?; + let print_mode = match group.mode() { + GroupMode::Expand | GroupMode::Propagated => PrintMode::Expanded, + GroupMode::Flat => self.flat_group_print_mode( + TagKind::ConditionalGroup, + None, + args, + queue, + stack, + )?, + }; + + stack.push(TagKind::ConditionalGroup, args.with_print_mode(print_mode)); } else { // Condition isn't met, render as normal content stack.push(TagKind::ConditionalGroup, args); @@ -192,7 +212,7 @@ impl<'a> Printer<'a> { FormatElement::Tag(StartConditionalContent(Condition { mode, group_id })) => { let group_mode = match group_id { None => args.mode(), - Some(id) => self.state.group_modes.unwrap_print_mode(*id, element), + Some(id) => self.state.group_modes.get_print_mode(*id)?, }; if *mode == group_mode { @@ -203,7 +223,7 @@ impl<'a> Printer<'a> { } FormatElement::Tag(StartIndentIfGroupBreaks(group_id)) => { - let group_mode = self.state.group_modes.unwrap_print_mode(*group_id, element); + let group_mode = self.state.group_modes.get_print_mode(*group_id)?; let args = match group_mode { PrintMode::Flat => args, @@ -221,6 +241,8 @@ impl<'a> Printer<'a> { FormatElement::Tag(StartVerbatim(kind)) => { if let VerbatimKind::Verbatim { length } = kind { + // SAFETY: Ruff only supports formatting files <= 4GB + #[allow(clippy::cast_possible_truncation)] self.state.verbatim_markers.push(TextRange::at( TextSize::from(self.state.buffer.len() as u32), *length, @@ -234,9 +256,7 @@ impl<'a> Printer<'a> { let condition_met = match condition { Some(condition) => { let group_mode = match condition.group_id { - Some(group_id) => { - self.state.group_modes.unwrap_print_mode(group_id, element) - } + Some(group_id) => self.state.group_modes.get_print_mode(group_id)?, None => args.mode(), }; @@ -286,47 +306,46 @@ impl<'a> Printer<'a> { result } - fn print_group( + fn flat_group_print_mode( &mut self, kind: TagKind, - mode: GroupMode, + id: Option, args: PrintElementArgs, - queue: &mut PrintQueue<'a>, + queue: &PrintQueue<'a>, stack: &mut PrintCallStack, ) -> PrintResult { - let group_mode = match mode { - GroupMode::Expand | GroupMode::Propagated => PrintMode::Expanded, - GroupMode::Flat => { - match args.mode() { - PrintMode::Flat if self.state.measured_group_fits => { - // A parent group has already verified that this group fits on a single line - // Thus, just continue in flat mode - PrintMode::Flat - } - // The printer is either in expanded mode or it's necessary to re-measure if the group fits - // because the printer printed a line break - _ => { - self.state.measured_group_fits = true; - - // Measure to see if the group fits up on a single line. If that's the case, - // print the group in "flat" mode, otherwise continue in expanded mode - stack.push(kind, args.with_print_mode(PrintMode::Flat)); - let fits = self.fits(queue, stack)?; - stack.pop(kind)?; - - if fits { - PrintMode::Flat - } else { - PrintMode::Expanded - } - } + let print_mode = match args.mode() { + PrintMode::Flat if self.state.measured_group_fits => { + // A parent group has already verified that this group fits on a single line + // Thus, just continue in flat mode + PrintMode::Flat + } + // The printer is either in expanded mode or it's necessary to re-measure if the group fits + // because the printer printed a line break + _ => { + self.state.measured_group_fits = true; + + if let Some(id) = id { + self.state + .group_modes + .insert_print_mode(id, PrintMode::Flat); + } + + // Measure to see if the group fits up on a single line. If that's the case, + // print the group in "flat" mode, otherwise continue in expanded mode + stack.push(kind, args.with_print_mode(PrintMode::Flat)); + let fits = self.fits(queue, stack)?; + stack.pop(kind)?; + + if fits { + PrintMode::Flat + } else { + PrintMode::Expanded } } }; - stack.push(kind, args.with_print_mode(group_mode)); - - Ok(group_mode) + Ok(print_mode) } fn print_text(&mut self, text: &str, source_range: Option) { @@ -384,7 +403,7 @@ impl<'a> Printer<'a> { if let Some(last) = self.state.source_markers.last() { if last != &marker { - self.state.source_markers.push(marker) + self.state.source_markers.push(marker); } } else { self.state.source_markers.push(marker); @@ -396,7 +415,7 @@ impl<'a> Printer<'a> { queue: &mut PrintQueue<'a>, stack: &mut PrintCallStack, line_break: Option<&'a FormatElement>, - ) { + ) -> bool { let suffixes = self.state.line_suffixes.take_pending(); if suffixes.len() > 0 { @@ -411,20 +430,26 @@ impl<'a> Printer<'a> { queue.push(suffix); } LineSuffixEntry::Args(args) => { - stack.push(TagKind::LineSuffix, args); const LINE_SUFFIX_END: &FormatElement = &FormatElement::Tag(Tag::EndLineSuffix); + stack.push(TagKind::LineSuffix, args); + queue.push(LINE_SUFFIX_END); } } } + + true + } else { + false } } fn print_best_fitting( &mut self, variants: &'a BestFittingVariants, + mode: BestFittingMode, queue: &mut PrintQueue<'a>, stack: &mut PrintCallStack, ) -> PrintResult<()> { @@ -437,7 +462,7 @@ impl<'a> Printer<'a> { self.state.measured_group_fits = true; let normal_variants = &variants[..variants.len() - 1]; - for variant in normal_variants.iter() { + for variant in normal_variants { // Test if this variant fits and if so, use it. Otherwise try the next // variant. @@ -450,7 +475,9 @@ impl<'a> Printer<'a> { // args must be popped from the stack as soon as it sees the matching end entry. let content = &variant[1..]; - let entry_args = args.with_print_mode(PrintMode::Flat); + let entry_args = args + .with_print_mode(PrintMode::Flat) + .with_measure_mode(MeasureMode::from(mode)); queue.extend_back(content); stack.push(TagKind::Entry, entry_args); @@ -614,7 +641,7 @@ impl<'a> Printer<'a> { } } - /// Semantic alias for [Self::print_entry] for fill items. + /// Semantic alias for [`Self::print_entry`] for fill items. fn print_fill_item( &mut self, queue: &mut PrintQueue<'a>, @@ -624,7 +651,7 @@ impl<'a> Printer<'a> { self.print_entry(queue, stack, args) } - /// Semantic alias for [Self::print_entry] for fill separators. + /// Semantic alias for [`Self::print_entry`] for fill separators. fn print_fill_separator( &mut self, queue: &mut PrintQueue<'a>, @@ -636,7 +663,7 @@ impl<'a> Printer<'a> { /// Fully print an element (print the element itself and all its descendants) /// - /// Unlike [print_element], this function ensures the entire element has + /// Unlike [`print_element`], this function ensures the entire element has /// been printed when it returns and the queue is back to its original state fn print_entry( &mut self, @@ -695,8 +722,6 @@ impl<'a> Printer<'a> { .buffer .push_str(self.options.line_ending.as_str()); - self.state.generated_line += 1; - self.state.generated_column = 0; self.state.line_width = 0; // Fit's only tests if groups up to the first line break fit. @@ -704,12 +729,13 @@ impl<'a> Printer<'a> { self.state.measured_group_fits = false; } else { self.state.buffer.push(char); - self.state.generated_column += 1; + #[allow(clippy::cast_possible_truncation)] let char_width = if char == '\t' { - self.options.tab_width as usize + u32::from(self.options.tab_width) } else { - char.width().unwrap_or(0) + // SAFETY: A u32 is sufficient to represent the width of a file <= 4GB + char.width().unwrap_or(0) as u32 }; self.state.line_width += char_width; @@ -744,16 +770,23 @@ struct PrinterState<'a> { source_position: TextSize, pending_indent: Indention, measured_group_fits: bool, - generated_line: usize, - generated_column: usize, - line_width: usize, + line_width: u32, line_suffixes: LineSuffixes<'a>, verbatim_markers: Vec, group_modes: GroupModes, // Re-used queue to measure if a group fits. Optimisation to avoid re-allocating a new // vec every time a group gets measured fits_stack: Vec, - fits_queue: Vec<&'a [FormatElement]>, + fits_queue: Vec>, +} + +impl<'a> PrinterState<'a> { + fn with_capacity(capacity: usize) -> Self { + Self { + buffer: String::with_capacity(capacity), + ..Self::default() + } + } } /// Tracks the mode in which groups with ids are printed. Stores the groups at `group.id()` index. @@ -772,17 +805,15 @@ impl GroupModes { self.0[index] = Some(mode); } - fn get_print_mode(&self, group_id: GroupId) -> Option { + fn get_print_mode(&self, group_id: GroupId) -> PrintResult { let index = u32::from(group_id) as usize; - self.0 - .get(index) - .and_then(|option| option.as_ref().copied()) - } - fn unwrap_print_mode(&self, group_id: GroupId, next_element: &FormatElement) -> PrintMode { - self.get_print_mode(group_id).unwrap_or_else(|| { - panic!("Expected group with id {group_id:?} to exist but it wasn't present in the document. Ensure that a group with such a document appears in the document before the element {next_element:?}.") - }) + match self.0.get(index) { + Some(Some(print_mode)) => Ok(*print_mode), + None | Some(None) => Err(PrintError::InvalidDocument( + InvalidDocumentError::UnknownGroupId { group_id }, + )), + } } } @@ -796,7 +827,7 @@ enum Indention { } impl Indention { - const fn is_empty(&self) -> bool { + const fn is_empty(self) -> bool { matches!(self, Indention::Level(0)) } @@ -806,27 +837,27 @@ impl Indention { } /// Returns the indention level - fn level(&self) -> u16 { + fn level(self) -> u16 { match self { - Indention::Level(count) => *count, - Indention::Align { level: indent, .. } => *indent, + Indention::Level(count) => count, + Indention::Align { level: indent, .. } => indent, } } /// Returns the number of trailing align spaces or 0 if none - fn align(&self) -> u8 { + fn align(self) -> u8 { match self { Indention::Level(_) => 0, - Indention::Align { align, .. } => (*align).into(), + Indention::Align { align, .. } => align.into(), } } /// Increments the level by one. /// - /// The behaviour depends on the [`indent_style`][IndentStyle] if this is an [Indent::Align]: + /// The behaviour depends on the [`indent_style`][IndentStyle] if this is an [`Indent::Align`]: /// - **Tabs**: `align` is converted into an indent. This results in `level` increasing by two: once for the align, once for the level increment /// - **Spaces**: Increments the `level` by one and keeps the `align` unchanged. - /// Keeps any the current value is [Indent::Align] and increments the level by one. + /// Keeps any the current value is [`Indent::Align`] and increments the level by one. fn increment_level(self, indent_style: IndentStyle) -> Self { match self { Indention::Level(count) => Indention::Level(count + 1), @@ -843,8 +874,8 @@ impl Indention { } /// Decrements the indent by one by: - /// - Reducing the level by one if this is [Indent::Level] - /// - Removing the `align` if this is [Indent::Align] + /// - Reducing the level by one if this is [`Indent::Level`] + /// - Removing the `align` if this is [`Indent::Align`] /// /// No-op if the level is already zero. fn decrement(self) -> Self { @@ -856,7 +887,7 @@ impl Indention { /// Adds an `align` of `count` spaces to the current indention. /// - /// It increments the `level` value if the current value is [Indent::IndentAlign]. + /// It increments the `level` value if the current value is [`Indent::IndentAlign`]. fn set_align(self, count: NonZeroU8) -> Self { match self { Indention::Level(indent_count) => Indention::Align { @@ -960,9 +991,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { Ok(true) } - /// Tests if the content of a `Fill` item fits in [PrintMode::Flat]. + /// Tests if the content of a `Fill` item fits in [`PrintMode::Flat`]. /// - /// Returns `Err` if the top element of the queue is not a [Tag::StartEntry] + /// Returns `Err` if the top element of the queue is not a [`Tag::StartEntry`] /// or if the document has any mismatching start/end tags. fn fill_item_fits(&mut self) -> PrintResult { self.fill_entry_fits(PrintMode::Flat) @@ -970,17 +1001,17 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { /// Tests if the content of a `Fill` separator fits with `mode`. /// - /// Returns `Err` if the top element of the queue is not a [Tag::StartEntry] + /// Returns `Err` if the top element of the queue is not a [`Tag::StartEntry`] /// or if the document has any mismatching start/end tags. fn fill_separator_fits(&mut self, mode: PrintMode) -> PrintResult { self.fill_entry_fits(mode) } - /// Tests if the elements between the [Tag::StartEntry] and [Tag::EndEntry] + /// Tests if the elements between the [`Tag::StartEntry`] and [`Tag::EndEntry`] /// of a fill item or separator fits with `mode`. /// - /// Returns `Err` if the queue isn't positioned at a [Tag::StartEntry] or if - /// the matching [Tag::EndEntry] is missing. + /// Returns `Err` if the queue isn't positioned at a [`Tag::StartEntry`] or if + /// the matching [`Tag::EndEntry`] is missing. fn fill_entry_fits(&mut self, mode: PrintMode) -> PrintResult { let start_entry = self.queue.top(); @@ -1002,6 +1033,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { /// Tests if the passed element fits on the current line or not. fn fits_element(&mut self, element: &'a FormatElement) -> PrintResult { + #[allow(clippy::enum_glob_use)] use Tag::*; let args = self.stack.top(); @@ -1061,10 +1093,13 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { FormatElement::SourcePosition(_) => {} - FormatElement::BestFitting { variants } => { - let slice = match args.mode() { - PrintMode::Flat => variants.most_flat(), - PrintMode::Expanded => variants.most_expanded(), + FormatElement::BestFitting { variants, mode } => { + let (slice, args) = match args.mode() { + PrintMode::Flat => ( + variants.most_flat(), + args.with_measure_mode(MeasureMode::from(*mode)), + ), + PrintMode::Expanded => (variants.most_expanded(), args), }; if !matches!(slice.first(), Some(FormatElement::Tag(Tag::StartEntry))) { @@ -1098,7 +1133,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { } FormatElement::Tag(StartGroup(group)) => { - return self.fits_group(TagKind::Group, group.mode(), group.id(), args); + return Ok(self.fits_group(TagKind::Group, group.mode(), group.id(), args)); } FormatElement::Tag(StartConditionalGroup(group)) => { @@ -1106,26 +1141,24 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { let print_mode = match condition.group_id { None => args.mode(), - Some(group_id) => self - .group_modes() - .get_print_mode(group_id) - .unwrap_or_else(|| args.mode()), + Some(group_id) => self.group_modes().get_print_mode(group_id)?, }; if condition.mode == print_mode { - return self.fits_group(TagKind::ConditionalGroup, group.mode(), None, args); - } else { - self.stack.push(TagKind::ConditionalGroup, args); + return Ok(self.fits_group( + TagKind::ConditionalGroup, + group.mode(), + None, + args, + )); } + self.stack.push(TagKind::ConditionalGroup, args); } FormatElement::Tag(StartConditionalContent(condition)) => { let print_mode = match condition.group_id { None => args.mode(), - Some(group_id) => self - .group_modes() - .get_print_mode(group_id) - .unwrap_or_else(|| args.mode()), + Some(group_id) => self.group_modes().get_print_mode(group_id)?, }; if condition.mode == print_mode { @@ -1136,10 +1169,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { } FormatElement::Tag(StartIndentIfGroupBreaks(id)) => { - let print_mode = self - .group_modes() - .get_print_mode(*id) - .unwrap_or_else(|| args.mode()); + let print_mode = self.group_modes().get_print_mode(*id)?; match print_mode { PrintMode::Flat => { @@ -1170,10 +1200,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { let condition_met = match condition { Some(condition) => { let group_mode = match condition.group_id { - Some(group_id) => self - .group_modes() - .get_print_mode(group_id) - .unwrap_or_else(|| args.mode()), + Some(group_id) => self.group_modes().get_print_mode(group_id)?, None => args.mode(), }; @@ -1188,14 +1215,14 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { TagKind::FitsExpanded, args.with_print_mode(PrintMode::Expanded) .with_measure_mode(MeasureMode::AllLines), - ) + ); } else { if propagate_expand.get() && args.mode().is_flat() { return Ok(Fits::No); } // As usual - self.stack.push(TagKind::FitsExpanded, args) + self.stack.push(TagKind::FitsExpanded, args); } } @@ -1229,20 +1256,20 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { fn fits_group( &mut self, kind: TagKind, - mode: GroupMode, + group_mode: GroupMode, id: Option, args: PrintElementArgs, - ) -> PrintResult { - if self.must_be_flat && !mode.is_flat() { - return Ok(Fits::No); + ) -> Fits { + if self.must_be_flat && !group_mode.is_flat() { + return Fits::No; } // Continue printing groups in expanded mode if measuring a `best_fitting` element where // a group expands. - let print_mode = if !mode.is_flat() { - PrintMode::Expanded - } else { + let print_mode = if group_mode.is_flat() { args.mode() + } else { + PrintMode::Expanded }; self.stack.push(kind, args.with_print_mode(print_mode)); @@ -1251,32 +1278,33 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { self.group_modes_mut().insert_print_mode(id, print_mode); } - Ok(Fits::Maybe) + Fits::Maybe } fn fits_text(&mut self, text: &str, args: PrintElementArgs) -> Fits { let indent = std::mem::take(&mut self.state.pending_indent); - self.state.line_width += indent.level() as usize * self.options().indent_width() as usize - + indent.align() as usize; + self.state.line_width += u32::from(indent.level()) + * u32::from(self.options().indent_width()) + + u32::from(indent.align()); for c in text.chars() { let char_width = match c { - '\t' => self.options().tab_width as usize, + '\t' => u32::from(self.options().tab_width), '\n' => { if self.must_be_flat { return Fits::No; - } else { - match args.measure_mode() { - MeasureMode::FirstLine => return Fits::Yes, - MeasureMode::AllLines => { - self.state.line_width = 0; - self.state.pending_indent = args.indention(); - continue; - } + } + match args.measure_mode() { + MeasureMode::FirstLine => return Fits::Yes, + MeasureMode::AllLines => { + self.state.line_width = 0; + continue; } - }; + } } - c => c.width().unwrap_or(0), + // SAFETY: A u32 is sufficient to format files <= 4GB + #[allow(clippy::cast_possible_truncation)] + c => c.width().unwrap_or(0) as u32, }; self.state.line_width += char_width; } @@ -1358,9 +1386,10 @@ enum Fits { impl From for Fits { fn from(value: bool) -> Self { - match value { - true => Fits::Yes, - false => Fits::No, + if value { + Fits::Yes + } else { + Fits::No } } } @@ -1370,7 +1399,7 @@ impl From for Fits { struct FitsState { pending_indent: Indention, has_line_suffix: bool, - line_width: usize, + line_width: u32, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -1380,11 +1409,20 @@ enum MeasureMode { /// Returns FirstLine, - /// The content only fits if non of the lines exceed the print width. Lines are terminated by either + /// The content only fits if none of the lines exceed the print width. Lines are terminated by either /// a hard line break or a soft line break in [`PrintMode::Expanded`]. AllLines, } +impl From for MeasureMode { + fn from(value: BestFittingMode) -> Self { + match value { + BestFittingMode::FirstLine => Self::FirstLine, + BestFittingMode::AllLines => Self::AllLines, + } + } +} + #[cfg(test)] mod tests { use crate::prelude::*; @@ -1424,7 +1462,7 @@ mod tests { ], }); - assert_eq!(r#"["a", "b", "c", "d"]"#, result.as_code()) + assert_eq!(r#"["a", "b", "c", "d"]"#, result.as_code()); } #[test] @@ -1453,7 +1491,7 @@ mod tests { b a"#, formatted.as_code() - ) + ); } #[test] @@ -1495,13 +1533,13 @@ two lines`, "b", ]"#, result.as_code() - ) + ); } #[test] fn it_breaks_a_group_if_it_contains_a_hard_line_break() { let result = format(&group(&format_args![text("a"), block_indent(&text("b"))])); - assert_eq!("a\n b\n", result.as_code()) + assert_eq!("a\n b\n", result.as_code()); } #[test] @@ -1565,7 +1603,7 @@ two lines`, text("b"), ]); - assert_eq!("a\nb", result.as_code()) + assert_eq!("a\nb", result.as_code()); } #[test] @@ -1578,7 +1616,7 @@ two lines`, text("b"), ]); - assert_eq!("a\n\n\n\nb", result.as_code()) + assert_eq!("a\n\n\n\nb", result.as_code()); } #[test] @@ -1592,7 +1630,7 @@ two lines`, text("b"), ]); - assert_eq!("a\n\n\nb", result.as_code()) + assert_eq!("a\n\n\nb", result.as_code()); } #[test] @@ -1654,7 +1692,7 @@ two lines`, assert_eq!( printed.as_code(), "1, 2, 3,\n723493294,\n[5],\n[\n\t123456789\n]" - ) + ); } #[test] @@ -1681,10 +1719,10 @@ two lines`, text("]") ]), text(";"), - &line_suffix(&format_args![space(), text("// trailing")]) + line_suffix(&format_args![space(), text("// trailing")]) ]); - assert_eq!(printed.as_code(), "[1, 2, 3]; // trailing") + assert_eq!(printed.as_code(), "[1, 2, 3]; // trailing"); } #[test] diff --git a/crates/ruff_formatter/src/printer/printer_options/mod.rs b/crates/ruff_formatter/src/printer/printer_options/mod.rs index 36b754fcccf5d..d68f60ef2ed3f 100644 --- a/crates/ruff_formatter/src/printer/printer_options/mod.rs +++ b/crates/ruff_formatter/src/printer/printer_options/mod.rs @@ -1,6 +1,6 @@ use crate::{FormatOptions, IndentStyle, LineWidth}; -/// Options that affect how the [crate::Printer] prints the format tokens +/// Options that affect how the [`crate::Printer`] prints the format tokens #[derive(Clone, Debug, Eq, PartialEq)] pub struct PrinterOptions { /// Width of a single tab character (does it equal 2, 4, ... spaces?) @@ -33,7 +33,7 @@ impl Default for PrintWidth { impl From for PrintWidth { fn from(width: LineWidth) -> Self { - Self(u16::from(width) as u32) + Self(u32::from(u16::from(width))) } } @@ -43,6 +43,12 @@ impl From for usize { } } +impl From for u32 { + fn from(width: PrintWidth) -> Self { + width.0 + } +} + impl<'a, O> From<&'a O> for PrinterOptions where O: FormatOptions, @@ -55,11 +61,13 @@ where } impl PrinterOptions { + #[must_use] pub fn with_print_width(mut self, width: PrintWidth) -> Self { self.print_width = width; self } + #[must_use] pub fn with_indent(mut self, style: IndentStyle) -> Self { self.indent_style = style; @@ -108,7 +116,7 @@ impl Default for PrinterOptions { PrinterOptions { tab_width: 2, print_width: PrintWidth::default(), - indent_style: Default::default(), + indent_style: IndentStyle::default(), line_ending: LineEnding::LineFeed, } } diff --git a/crates/ruff_formatter/src/printer/queue.rs b/crates/ruff_formatter/src/printer/queue.rs index 6ef645b339215..07b83a03fa74f 100644 --- a/crates/ruff_formatter/src/printer/queue.rs +++ b/crates/ruff_formatter/src/printer/queue.rs @@ -1,58 +1,25 @@ use crate::format_element::tag::TagKind; use crate::prelude::Tag; -use crate::printer::stack::{Stack, StackedStack}; use crate::printer::{invalid_end_tag, invalid_start_tag}; use crate::{FormatElement, PrintResult}; use std::fmt::Debug; use std::iter::FusedIterator; use std::marker::PhantomData; -/// Queue of [FormatElement]s. +/// Queue of [`FormatElement`]s. pub(super) trait Queue<'a> { - type Stack: Stack<&'a [FormatElement]>; - - fn stack(&self) -> &Self::Stack; - - fn stack_mut(&mut self) -> &mut Self::Stack; - - fn next_index(&self) -> usize; - - fn set_next_index(&mut self, index: usize); - /// Pops the element at the end of the queue. - fn pop(&mut self) -> Option<&'a FormatElement> { - match self.stack().top() { - Some(top_slice) => { - // SAFETY: Safe because queue ensures that slices inside `slices` are never empty. - let next_index = self.next_index(); - let element = &top_slice[next_index]; - - if next_index + 1 == top_slice.len() { - self.stack_mut().pop().unwrap(); - self.set_next_index(0); - } else { - self.set_next_index(next_index + 1); - } + fn pop(&mut self) -> Option<&'a FormatElement>; - Some(element) - } - None => None, - } - } - - /// Returns the next element, not traversing into [FormatElement::Interned]. - fn top_with_interned(&self) -> Option<&'a FormatElement> { - self.stack() - .top() - .map(|top_slice| &top_slice[self.next_index()]) - } + /// Returns the next element, not traversing into [`FormatElement::Interned`]. + fn top_with_interned(&self) -> Option<&'a FormatElement>; - /// Returns the next element, recursively resolving the first element of [FormatElement::Interned]. + /// Returns the next element, recursively resolving the first element of [`FormatElement::Interned`]. fn top(&self) -> Option<&'a FormatElement> { let mut top = self.top_with_interned(); while let Some(FormatElement::Interned(interned)) = top { - top = interned.first() + top = interned.first(); } top @@ -60,33 +27,14 @@ pub(super) trait Queue<'a> { /// Queues a single element to process before the other elements in this queue. fn push(&mut self, element: &'a FormatElement) { - self.extend_back(std::slice::from_ref(element)) + self.extend_back(std::slice::from_ref(element)); } /// Queues a slice of elements to process before the other elements in this queue. - fn extend_back(&mut self, elements: &'a [FormatElement]) { - match elements { - [] => { - // Don't push empty slices - } - slice => { - let next_index = self.next_index(); - let stack = self.stack_mut(); - if let Some(top) = stack.pop() { - stack.push(&top[next_index..]) - } - - stack.push(slice); - self.set_next_index(0); - } - } - } + fn extend_back(&mut self, elements: &'a [FormatElement]); /// Removes top slice. - fn pop_slice(&mut self) -> Option<&'a [FormatElement]> { - self.set_next_index(0); - self.stack_mut().pop() - } + fn pop_slice(&mut self) -> Option<&'a [FormatElement]>; /// Skips all content until it finds the corresponding end tag with the given kind. fn skip_content(&mut self, kind: TagKind) @@ -112,100 +60,131 @@ pub(super) trait Queue<'a> { /// Queue with the elements to print. #[derive(Debug, Default, Clone)] pub(super) struct PrintQueue<'a> { - slices: Vec<&'a [FormatElement]>, - next_index: usize, + element_slices: Vec>, } impl<'a> PrintQueue<'a> { pub(super) fn new(slice: &'a [FormatElement]) -> Self { - let slices = match slice { - [] => Vec::default(), - slice => vec![slice], - }; - Self { - slices, - next_index: 0, + element_slices: if slice.is_empty() { + Vec::new() + } else { + vec![slice.iter()] + }, } } - - pub(super) fn is_empty(&self) -> bool { - self.slices.is_empty() - } } impl<'a> Queue<'a> for PrintQueue<'a> { - type Stack = Vec<&'a [FormatElement]>; - - fn stack(&self) -> &Self::Stack { - &self.slices + fn pop(&mut self) -> Option<&'a FormatElement> { + let elements = self.element_slices.last_mut()?; + elements.next().or_else(|| { + self.element_slices.pop(); + let elements = self.element_slices.last_mut()?; + elements.next() + }) } - fn stack_mut(&mut self) -> &mut Self::Stack { - &mut self.slices + fn top_with_interned(&self) -> Option<&'a FormatElement> { + let mut slices = self.element_slices.iter().rev(); + let slice = slices.next()?; + + match slice.as_slice().first() { + Some(element) => Some(element), + None => { + if let Some(next_elements) = slices.next() { + next_elements.as_slice().first() + } else { + None + } + } + } } - fn next_index(&self) -> usize { - self.next_index + fn extend_back(&mut self, elements: &'a [FormatElement]) { + if !elements.is_empty() { + self.element_slices.push(elements.iter()); + } } - fn set_next_index(&mut self, index: usize) { - self.next_index = index + /// Removes top slice. + fn pop_slice(&mut self) -> Option<&'a [FormatElement]> { + self.element_slices + .pop() + .map(|elements| elements.as_slice()) } } /// Queue for measuring if an element fits on the line. /// -/// The queue is a view on top of the [PrintQueue] because no elements should be removed -/// from the [PrintQueue] while measuring. +/// The queue is a view on top of the [`PrintQueue`] because no elements should be removed +/// from the [`PrintQueue`] while measuring. #[must_use] #[derive(Debug)] pub(super) struct FitsQueue<'a, 'print> { - stack: StackedStack<'print, &'a [FormatElement]>, - next_index: usize, + queue: PrintQueue<'a>, + rest_elements: std::slice::Iter<'print, std::slice::Iter<'a, FormatElement>>, } impl<'a, 'print> FitsQueue<'a, 'print> { pub(super) fn new( - print_queue: &'print PrintQueue<'a>, - saved: Vec<&'a [FormatElement]>, + rest_queue: &'print PrintQueue<'a>, + queue_vec: Vec>, ) -> Self { - let stack = StackedStack::with_vec(&print_queue.slices, saved); - Self { - stack, - next_index: print_queue.next_index, + queue: PrintQueue { + element_slices: queue_vec, + }, + rest_elements: rest_queue.element_slices.iter(), } } - pub(super) fn finish(self) -> Vec<&'a [FormatElement]> { - self.stack.into_vec() + pub(super) fn finish(self) -> Vec> { + self.queue.element_slices } } impl<'a, 'print> Queue<'a> for FitsQueue<'a, 'print> { - type Stack = StackedStack<'print, &'a [FormatElement]>; - - fn stack(&self) -> &Self::Stack { - &self.stack + fn pop(&mut self) -> Option<&'a FormatElement> { + self.queue.pop().or_else(|| { + if let Some(next_slice) = self.rest_elements.next_back() { + self.queue.extend_back(next_slice.as_slice()); + self.queue.pop() + } else { + None + } + }) } - fn stack_mut(&mut self) -> &mut Self::Stack { - &mut self.stack + fn top_with_interned(&self) -> Option<&'a FormatElement> { + self.queue.top_with_interned().or_else(|| { + if let Some(next_elements) = self.rest_elements.as_slice().last() { + next_elements.as_slice().first() + } else { + None + } + }) } - fn next_index(&self) -> usize { - self.next_index + fn extend_back(&mut self, elements: &'a [FormatElement]) { + if !elements.is_empty() { + self.queue.extend_back(elements); + } } - fn set_next_index(&mut self, index: usize) { - self.next_index = index; + /// Removes top slice. + fn pop_slice(&mut self) -> Option<&'a [FormatElement]> { + self.queue.pop_slice().or_else(|| { + self.rest_elements + .next_back() + .map(std::slice::Iter::as_slice) + }) } } -/// Iterator that calls [Queue::pop] until it reaches the end of the document. +/// Iterator that calls [`Queue::pop`] until it reaches the end of the document. /// -/// The iterator traverses into the content of any [FormatElement::Interned]. +/// The iterator traverses into the content of any [`FormatElement::Interned`]. pub(super) struct QueueIterator<'a, 'q, Q: Queue<'a>> { queue: &'q mut Q, lifetime: PhantomData<&'a ()>, @@ -252,32 +231,31 @@ where type Item = &'a FormatElement; fn next(&mut self) -> Option { - match self.depth { - 0 => None, - _ => { - let mut top = self.queue.pop(); - - while let Some(FormatElement::Interned(interned)) = top { - self.queue.extend_back(interned); - top = self.queue.pop(); - } + if self.depth == 0 { + None + } else { + let mut top = self.queue.pop(); + + while let Some(FormatElement::Interned(interned)) = top { + self.queue.extend_back(interned); + top = self.queue.pop(); + } - match top.expect("Missing end signal.") { - element @ FormatElement::Tag(tag) if tag.kind() == self.kind => { - if tag.is_start() { - self.depth += 1; - } else { - self.depth -= 1; + match top.expect("Missing end signal.") { + element @ FormatElement::Tag(tag) if tag.kind() == self.kind => { + if tag.is_start() { + self.depth += 1; + } else { + self.depth -= 1; - if self.depth == 0 { - return None; - } + if self.depth == 0 { + return None; } - - Some(element) } - element => Some(element), + + Some(element) } + element => Some(element), } } } @@ -287,7 +265,7 @@ impl<'a, Q> FusedIterator for QueueContentIterator<'a, '_, Q> where Q: Queue<'a> /// A predicate determining when to end measuring if some content fits on the line. /// -/// Called for every [`element`](FormatElement) in the [FitsQueue] when measuring if a content +/// Called for every [`element`](FormatElement) in the [`FitsQueue`] when measuring if a content /// fits on the line. The measuring of the content ends after the first element [`element`](FormatElement) for which this /// predicate returns `true` (similar to a take while iterator except that it takes while the predicate returns `false`). pub(super) trait FitsEndPredicate { @@ -303,7 +281,7 @@ impl FitsEndPredicate for AllPredicate { } } -/// Filter that takes all elements between two matching [Tag::StartEntry] and [Tag::EndEntry] tags. +/// Filter that takes all elements between two matching [`Tag::StartEntry`] and [`Tag::EndEntry`] tags. #[derive(Debug)] pub(super) enum SingleEntryPredicate { Entry { depth: usize }, diff --git a/crates/ruff_formatter/src/printer/stack.rs b/crates/ruff_formatter/src/printer/stack.rs index 1bc8da80473da..2d9c6887194ef 100644 --- a/crates/ruff_formatter/src/printer/stack.rs +++ b/crates/ruff_formatter/src/printer/stack.rs @@ -19,7 +19,7 @@ impl Stack for Vec { } fn push(&mut self, value: T) { - self.push(value) + self.push(value); } fn top(&self) -> Option<&T> { @@ -35,7 +35,7 @@ impl Stack for Vec { #[derive(Debug, Clone)] pub(super) struct StackedStack<'a, T> { /// The content of the original stack. - original: &'a [T], + original: std::slice::Iter<'a, T>, /// Items that have been pushed since the creation of this stack and aren't part of the `original` stack. stack: Vec, @@ -49,7 +49,10 @@ impl<'a, T> StackedStack<'a, T> { /// Creates a new stack that uses `stack` for storing its elements. pub(super) fn with_vec(original: &'a [T], stack: Vec) -> Self { - Self { original, stack } + Self { + original: original.iter(), + stack, + } } /// Returns the underlying `stack` vector. @@ -63,13 +66,9 @@ where T: Copy, { fn pop(&mut self) -> Option { - self.stack.pop().or_else(|| match self.original { - [rest @ .., last] => { - self.original = rest; - Some(*last) - } - _ => None, - }) + self.stack + .pop() + .or_else(|| self.original.next_back().copied()) } fn push(&mut self, value: T) { @@ -77,11 +76,13 @@ where } fn top(&self) -> Option<&T> { - self.stack.last().or_else(|| self.original.last()) + self.stack + .last() + .or_else(|| self.original.as_slice().last()) } fn is_empty(&self) -> bool { - self.original.is_empty() && self.stack.is_empty() + self.stack.is_empty() && self.original.len() == 0 } } diff --git a/crates/ruff_python_ast/Cargo.toml b/crates/ruff_python_ast/Cargo.toml index b85f740223267..ac33034c90eef 100644 --- a/crates/ruff_python_ast/Cargo.toml +++ b/crates/ruff_python_ast/Cargo.toml @@ -10,8 +10,6 @@ documentation = { workspace = true } repository = { workspace = true } license = { workspace = true } - - [lib] [dependencies] diff --git a/crates/ruff_python_ast/src/all.rs b/crates/ruff_python_ast/src/all.rs index 27955a845ef96..3f738984b55c8 100644 --- a/crates/ruff_python_ast/src/all.rs +++ b/crates/ruff_python_ast/src/all.rs @@ -1,3 +1,4 @@ +use crate::helpers::map_subscript; use crate::{self as ast, Constant, Expr, Stmt}; use bitflags::bitflags; @@ -23,7 +24,7 @@ where fn add_to_names<'a>(elts: &'a [Expr], names: &mut Vec<&'a str>, flags: &mut DunderAllFlags) { for elt in elts { if let Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = elt { @@ -63,13 +64,12 @@ where } Expr::Call(ast::ExprCall { func, - args, - keywords, + arguments: ast::Arguments { args, keywords, .. }, .. }) => { - // Allow `tuple()` and `list()` calls. + // Allow `tuple()`, `list()`, and their generic forms, like `list[int]()`. if keywords.is_empty() && args.len() <= 1 { - if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { + if let Expr::Name(ast::ExprName { id, .. }) = map_subscript(func) { let id = id.as_str(); if matches!(id, "tuple" | "list") && is_builtin(id) { let [arg] = args.as_slice() else { diff --git a/crates/ruff_python_ast/src/call_path.rs b/crates/ruff_python_ast/src/call_path.rs index c11c456fe70b7..fe8043a106eee 100644 --- a/crates/ruff_python_ast/src/call_path.rs +++ b/crates/ruff_python_ast/src/call_path.rs @@ -1,6 +1,7 @@ -use crate::{nodes, Expr}; use smallvec::{smallvec, SmallVec}; +use crate::{nodes, Expr}; + /// A representation of a qualified name, like `typing.List`. pub type CallPath<'a> = SmallVec<[&'a str; 8]>; @@ -141,12 +142,31 @@ pub fn compose_call_path(expr: &Expr) -> Option { /// Format a call path for display. pub fn format_call_path(call_path: &[&str]) -> String { - if call_path + if call_path.first().map_or(false, |first| first.is_empty()) { + // If the first segment is empty, the `CallPath` is that of a builtin. + // Ex) `["", "bool"]` -> `"bool"` + call_path[1..].join(".") + } else if call_path .first() - .expect("Unable to format empty call path") - .is_empty() + .map_or(false, |first| matches!(*first, ".")) { - call_path[1..].join(".") + // If the call path is dot-prefixed, it's an unresolved relative import. + // Ex) `[".foo", "bar"]` -> `".foo.bar"` + let mut formatted = String::new(); + let mut iter = call_path.iter(); + for segment in iter.by_ref() { + if *segment == "." { + formatted.push('.'); + } else { + formatted.push_str(segment); + break; + } + } + for segment in iter { + formatted.push('.'); + formatted.push_str(segment); + } + formatted } else { call_path.join(".") } diff --git a/crates/ruff_python_ast/src/cast.rs b/crates/ruff_python_ast/src/cast.rs deleted file mode 100644 index 1b59f69b2053c..0000000000000 --- a/crates/ruff_python_ast/src/cast.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{nodes, Decorator, Stmt}; - -pub fn name(stmt: &Stmt) -> &str { - match stmt { - Stmt::FunctionDef(nodes::StmtFunctionDef { name, .. }) - | Stmt::AsyncFunctionDef(nodes::StmtAsyncFunctionDef { name, .. }) => name.as_str(), - _ => panic!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef"), - } -} - -pub fn decorator_list(stmt: &Stmt) -> &[Decorator] { - match stmt { - Stmt::FunctionDef(nodes::StmtFunctionDef { decorator_list, .. }) - | Stmt::AsyncFunctionDef(nodes::StmtAsyncFunctionDef { decorator_list, .. }) => { - decorator_list - } - _ => panic!("Expected Stmt::FunctionDef | Stmt::AsyncFunctionDef"), - } -} diff --git a/crates/ruff_python_ast/src/comparable.rs b/crates/ruff_python_ast/src/comparable.rs index f2a5956185b03..6051ace1d4db1 100644 --- a/crates/ruff_python_ast/src/comparable.rs +++ b/crates/ruff_python_ast/src/comparable.rs @@ -326,8 +326,18 @@ impl<'a> From<&'a ast::Constant> for ComparableConstant<'a> { match constant { ast::Constant::None => Self::None, ast::Constant::Bool(value) => Self::Bool(value), - ast::Constant::Str(value) => Self::Str(value), - ast::Constant::Bytes(value) => Self::Bytes(value), + ast::Constant::Str(ast::StringConstant { + value, + // Compare strings based on resolved value, not representation (i.e., ignore whether + // the string was implicitly concatenated). + implicit_concatenated: _, + }) => Self::Str(value), + ast::Constant::Bytes(ast::BytesConstant { + value, + // Compare bytes based on resolved value, not representation (i.e., ignore whether + // the bytes were implicitly concatenated). + implicit_concatenated: _, + }) => Self::Bytes(value), ast::Constant::Int(value) => Self::Int(value), ast::Constant::Float(value) => Self::Float(value.to_bits()), ast::Constant::Complex { real, imag } => Self::Complex { @@ -341,21 +351,15 @@ impl<'a> From<&'a ast::Constant> for ComparableConstant<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct ComparableArguments<'a> { - posonlyargs: Vec>, - args: Vec>, - vararg: Option>, - kwonlyargs: Vec>, - kwarg: Option>, + args: Vec>, + keywords: Vec>, } impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> { fn from(arguments: &'a ast::Arguments) -> Self { Self { - posonlyargs: arguments.posonlyargs.iter().map(Into::into).collect(), args: arguments.args.iter().map(Into::into).collect(), - vararg: arguments.vararg.as_ref().map(Into::into), - kwonlyargs: arguments.kwonlyargs.iter().map(Into::into).collect(), - kwarg: arguments.kwarg.as_ref().map(Into::into), + keywords: arguments.keywords.iter().map(Into::into).collect(), } } } @@ -366,37 +370,64 @@ impl<'a> From<&'a Box> for ComparableArguments<'a> { } } -impl<'a> From<&'a Box> for ComparableArg<'a> { - fn from(arg: &'a Box) -> Self { +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct ComparableParameters<'a> { + posonlyargs: Vec>, + args: Vec>, + vararg: Option>, + kwonlyargs: Vec>, + kwarg: Option>, +} + +impl<'a> From<&'a ast::Parameters> for ComparableParameters<'a> { + fn from(parameters: &'a ast::Parameters) -> Self { + Self { + posonlyargs: parameters.posonlyargs.iter().map(Into::into).collect(), + args: parameters.args.iter().map(Into::into).collect(), + vararg: parameters.vararg.as_ref().map(Into::into), + kwonlyargs: parameters.kwonlyargs.iter().map(Into::into).collect(), + kwarg: parameters.kwarg.as_ref().map(Into::into), + } + } +} + +impl<'a> From<&'a Box> for ComparableParameters<'a> { + fn from(parameters: &'a Box) -> Self { + (parameters.as_ref()).into() + } +} + +impl<'a> From<&'a Box> for ComparableParameter<'a> { + fn from(arg: &'a Box) -> Self { (arg.as_ref()).into() } } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct ComparableArg<'a> { +pub struct ComparableParameter<'a> { arg: &'a str, annotation: Option>>, } -impl<'a> From<&'a ast::Arg> for ComparableArg<'a> { - fn from(arg: &'a ast::Arg) -> Self { +impl<'a> From<&'a ast::Parameter> for ComparableParameter<'a> { + fn from(arg: &'a ast::Parameter) -> Self { Self { - arg: arg.arg.as_str(), + arg: arg.name.as_str(), annotation: arg.annotation.as_ref().map(Into::into), } } } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct ComparableArgWithDefault<'a> { - def: ComparableArg<'a>, +pub struct ComparableParameterWithDefault<'a> { + def: ComparableParameter<'a>, default: Option>, } -impl<'a> From<&'a ast::ArgWithDefault> for ComparableArgWithDefault<'a> { - fn from(arg: &'a ast::ArgWithDefault) -> Self { +impl<'a> From<&'a ast::ParameterWithDefault> for ComparableParameterWithDefault<'a> { + fn from(arg: &'a ast::ParameterWithDefault) -> Self { Self { - def: (&arg.def).into(), + def: (&arg.parameter).into(), default: arg.default.as_ref().map(Into::into), } } @@ -511,7 +542,7 @@ pub struct ExprUnaryOp<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprLambda<'a> { - args: ComparableArguments<'a>, + parameters: Option>, body: Box>, } @@ -583,8 +614,7 @@ pub struct ExprCompare<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct ExprCall<'a> { func: Box>, - args: Vec>, - keywords: Vec>, + arguments: ComparableArguments<'a>, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -596,7 +626,7 @@ pub struct ExprFormattedValue<'a> { } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct ExprJoinedStr<'a> { +pub struct ExprFString<'a> { values: Vec>, } @@ -652,8 +682,8 @@ pub struct ExprSlice<'a> { } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct ExprLineMagic<'a> { - kind: ast::MagicKind, +pub struct ExprIpyEscapeCommand<'a> { + kind: ast::IpyEscapeKind, value: &'a str, } @@ -677,7 +707,7 @@ pub enum ComparableExpr<'a> { Compare(ExprCompare<'a>), Call(ExprCall<'a>), FormattedValue(ExprFormattedValue<'a>), - JoinedStr(ExprJoinedStr<'a>), + FString(ExprFString<'a>), Constant(ExprConstant<'a>), Attribute(ExprAttribute<'a>), Subscript(ExprSubscript<'a>), @@ -686,7 +716,7 @@ pub enum ComparableExpr<'a> { List(ExprList<'a>), Tuple(ExprTuple<'a>), Slice(ExprSlice<'a>), - LineMagic(ExprLineMagic<'a>), + IpyEscapeCommand(ExprIpyEscapeCommand<'a>), } impl<'a> From<&'a Box> for Box> { @@ -707,7 +737,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::BoolOp(ast::ExprBoolOp { op, values, - range: _range, + range: _, }) => Self::BoolOp(ExprBoolOp { op: (*op).into(), values: values.iter().map(Into::into).collect(), @@ -715,7 +745,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::NamedExpr(ast::ExprNamedExpr { target, value, - range: _range, + range: _, }) => Self::NamedExpr(ExprNamedExpr { target: target.into(), value: value.into(), @@ -724,7 +754,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { left, op, right, - range: _range, + range: _, }) => Self::BinOp(ExprBinOp { left: left.into(), op: (*op).into(), @@ -733,24 +763,24 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::UnaryOp(ast::ExprUnaryOp { op, operand, - range: _range, + range: _, }) => Self::UnaryOp(ExprUnaryOp { op: (*op).into(), operand: operand.into(), }), ast::Expr::Lambda(ast::ExprLambda { - args, + parameters, body, - range: _range, + range: _, }) => Self::Lambda(ExprLambda { - args: (args.as_ref()).into(), + parameters: parameters.as_ref().map(Into::into), body: body.into(), }), ast::Expr::IfExp(ast::ExprIfExp { test, body, orelse, - range: _range, + range: _, }) => Self::IfExp(ExprIfExp { test: test.into(), body: body.into(), @@ -759,7 +789,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::Dict(ast::ExprDict { keys, values, - range: _range, + range: _, }) => Self::Dict(ExprDict { keys: keys .iter() @@ -767,16 +797,13 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { .collect(), values: values.iter().map(Into::into).collect(), }), - ast::Expr::Set(ast::ExprSet { - elts, - range: _range, - }) => Self::Set(ExprSet { + ast::Expr::Set(ast::ExprSet { elts, range: _ }) => Self::Set(ExprSet { elts: elts.iter().map(Into::into).collect(), }), ast::Expr::ListComp(ast::ExprListComp { elt, generators, - range: _range, + range: _, }) => Self::ListComp(ExprListComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), @@ -784,7 +811,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::SetComp(ast::ExprSetComp { elt, generators, - range: _range, + range: _, }) => Self::SetComp(ExprSetComp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), @@ -793,7 +820,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { key, value, generators, - range: _range, + range: _, }) => Self::DictComp(ExprDictComp { key: key.into(), value: value.into(), @@ -802,34 +829,27 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, - range: _range, + range: _, }) => Self::GeneratorExp(ExprGeneratorExp { elt: elt.into(), generators: generators.iter().map(Into::into).collect(), }), - ast::Expr::Await(ast::ExprAwait { - value, - range: _range, - }) => Self::Await(ExprAwait { + ast::Expr::Await(ast::ExprAwait { value, range: _ }) => Self::Await(ExprAwait { value: value.into(), }), - ast::Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => Self::Yield(ExprYield { + ast::Expr::Yield(ast::ExprYield { value, range: _ }) => Self::Yield(ExprYield { value: value.as_ref().map(Into::into), }), - ast::Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) => Self::YieldFrom(ExprYieldFrom { - value: value.into(), - }), + ast::Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) => { + Self::YieldFrom(ExprYieldFrom { + value: value.into(), + }) + } ast::Expr::Compare(ast::ExprCompare { left, ops, comparators, - range: _range, + range: _, }) => Self::Compare(ExprCompare { left: left.into(), ops: ops.iter().copied().map(Into::into).collect(), @@ -837,36 +857,35 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { }), ast::Expr::Call(ast::ExprCall { func, - args, - keywords, - range: _range, + arguments, + range: _, }) => Self::Call(ExprCall { func: func.into(), - args: args.iter().map(Into::into).collect(), - keywords: keywords.iter().map(Into::into).collect(), + arguments: arguments.into(), }), ast::Expr::FormattedValue(ast::ExprFormattedValue { value, conversion, debug_text, format_spec, - range: _range, + range: _, }) => Self::FormattedValue(ExprFormattedValue { value: value.into(), conversion: *conversion, debug_text: debug_text.as_ref(), format_spec: format_spec.as_ref().map(Into::into), }), - ast::Expr::JoinedStr(ast::ExprJoinedStr { + ast::Expr::FString(ast::ExprFString { values, - range: _range, - }) => Self::JoinedStr(ExprJoinedStr { + implicit_concatenated: _, + range: _, + }) => Self::FString(ExprFString { values: values.iter().map(Into::into).collect(), }), ast::Expr::Constant(ast::ExprConstant { value, kind, - range: _range, + range: _, }) => Self::Constant(ExprConstant { value: value.into(), kind: kind.as_ref().map(String::as_str), @@ -875,7 +894,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { value, attr, ctx, - range: _range, + range: _, }) => Self::Attribute(ExprAttribute { value: value.into(), attr: attr.as_str(), @@ -885,7 +904,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { value, slice, ctx, - range: _range, + range: _, }) => Self::Subscript(ExprSubscript { value: value.into(), slice: slice.into(), @@ -894,23 +913,19 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::Starred(ast::ExprStarred { value, ctx, - range: _range, + range: _, }) => Self::Starred(ExprStarred { value: value.into(), ctx: ctx.into(), }), - ast::Expr::Name(ast::ExprName { - id, - ctx, - range: _range, - }) => Self::Name(ExprName { + ast::Expr::Name(ast::ExprName { id, ctx, range: _ }) => Self::Name(ExprName { id: id.as_str(), ctx: ctx.into(), }), ast::Expr::List(ast::ExprList { elts, ctx, - range: _range, + range: _, }) => Self::List(ExprList { elts: elts.iter().map(Into::into).collect(), ctx: ctx.into(), @@ -918,7 +933,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { ast::Expr::Tuple(ast::ExprTuple { elts, ctx, - range: _range, + range: _, }) => Self::Tuple(ExprTuple { elts: elts.iter().map(Into::into).collect(), ctx: ctx.into(), @@ -927,17 +942,17 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { lower, upper, step, - range: _range, + range: _, }) => Self::Slice(ExprSlice { lower: lower.as_ref().map(Into::into), upper: upper.as_ref().map(Into::into), step: step.as_ref().map(Into::into), }), - ast::Expr::LineMagic(ast::ExprLineMagic { + ast::Expr::IpyEscapeCommand(ast::ExprIpyEscapeCommand { kind, value, - range: _range, - }) => Self::LineMagic(ExprLineMagic { + range: _, + }) => Self::IpyEscapeCommand(ExprIpyEscapeCommand { kind: *kind, value: value.as_str(), }), @@ -947,32 +962,22 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtFunctionDef<'a> { - name: &'a str, - args: ComparableArguments<'a>, - body: Vec>, + is_async: bool, decorator_list: Vec>, - type_params: Vec>, - returns: Option>, -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct StmtAsyncFunctionDef<'a> { name: &'a str, - args: ComparableArguments<'a>, - body: Vec>, - decorator_list: Vec>, - type_params: Vec>, + type_params: Option>, + parameters: ComparableParameters<'a>, returns: Option>, + body: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtClassDef<'a> { + decorator_list: Vec>, name: &'a str, - bases: Vec>, - keywords: Vec>, + type_params: Option>, + arguments: Option>, body: Vec>, - decorator_list: Vec>, - type_params: Vec>, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -988,10 +993,29 @@ pub struct StmtDelete<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtTypeAlias<'a> { pub name: Box>, - pub type_params: Vec>, + pub type_params: Option>, pub value: Box>, } +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct ComparableTypeParams<'a> { + pub type_params: Vec>, +} + +impl<'a> From<&'a ast::TypeParams> for ComparableTypeParams<'a> { + fn from(type_params: &'a ast::TypeParams) -> Self { + Self { + type_params: type_params.iter().map(Into::into).collect(), + } + } +} + +impl<'a> From<&'a Box> for ComparableTypeParams<'a> { + fn from(type_params: &'a Box) -> Self { + type_params.as_ref().into() + } +} + #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableTypeParam<'a> { TypeVar(TypeParamTypeVar<'a>), @@ -1063,14 +1087,7 @@ pub struct StmtAnnAssign<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtFor<'a> { - target: ComparableExpr<'a>, - iter: ComparableExpr<'a>, - body: Vec>, - orelse: Vec>, -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct StmtAsyncFor<'a> { + is_async: bool, target: ComparableExpr<'a>, iter: ComparableExpr<'a>, body: Vec>, @@ -1093,12 +1110,7 @@ pub struct StmtIf<'a> { #[derive(Debug, PartialEq, Eq, Hash)] pub struct StmtWith<'a> { - items: Vec>, - body: Vec>, -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct StmtAsyncWith<'a> { + is_async: bool, items: Vec>, body: Vec>, } @@ -1121,14 +1133,7 @@ pub struct StmtTry<'a> { handlers: Vec>, orelse: Vec>, finalbody: Vec>, -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct StmtTryStar<'a> { - body: Vec>, - handlers: Vec>, - orelse: Vec>, - finalbody: Vec>, + is_star: bool, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -1165,15 +1170,14 @@ pub struct StmtExpr<'a> { } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct StmtLineMagic<'a> { - kind: ast::MagicKind, +pub struct StmtIpyEscapeCommand<'a> { + kind: ast::IpyEscapeKind, value: &'a str, } #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableStmt<'a> { FunctionDef(StmtFunctionDef<'a>), - AsyncFunctionDef(StmtAsyncFunctionDef<'a>), ClassDef(StmtClassDef<'a>), Return(StmtReturn<'a>), Delete(StmtDelete<'a>), @@ -1181,22 +1185,19 @@ pub enum ComparableStmt<'a> { AugAssign(StmtAugAssign<'a>), AnnAssign(StmtAnnAssign<'a>), For(StmtFor<'a>), - AsyncFor(StmtAsyncFor<'a>), While(StmtWhile<'a>), If(StmtIf<'a>), With(StmtWith<'a>), - AsyncWith(StmtAsyncWith<'a>), Match(StmtMatch<'a>), Raise(StmtRaise<'a>), Try(StmtTry<'a>), - TryStar(StmtTryStar<'a>), TypeAlias(StmtTypeAlias<'a>), Assert(StmtAssert<'a>), Import(StmtImport<'a>), ImportFrom(StmtImportFrom<'a>), Global(StmtGlobal<'a>), Nonlocal(StmtNonlocal<'a>), - LineMagic(StmtLineMagic<'a>), + IpyEscapeCommand(StmtIpyEscapeCommand<'a>), Expr(StmtExpr<'a>), Pass, Break, @@ -1207,79 +1208,57 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { fn from(stmt: &'a ast::Stmt) -> Self { match stmt { ast::Stmt::FunctionDef(ast::StmtFunctionDef { + is_async, name, - args, + parameters, body, decorator_list, returns, type_params, - range: _range, + range: _, }) => Self::FunctionDef(StmtFunctionDef { + is_async: *is_async, name: name.as_str(), - args: args.into(), + parameters: parameters.into(), body: body.iter().map(Into::into).collect(), decorator_list: decorator_list.iter().map(Into::into).collect(), returns: returns.as_ref().map(Into::into), - type_params: type_params.iter().map(Into::into).collect(), - }), - ast::Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - name, - args, - body, - decorator_list, - returns, - type_params, - range: _range, - }) => Self::AsyncFunctionDef(StmtAsyncFunctionDef { - name: name.as_str(), - args: args.into(), - body: body.iter().map(Into::into).collect(), - decorator_list: decorator_list.iter().map(Into::into).collect(), - returns: returns.as_ref().map(Into::into), - type_params: type_params.iter().map(Into::into).collect(), + type_params: type_params.as_ref().map(Into::into), }), ast::Stmt::ClassDef(ast::StmtClassDef { name, - bases, - keywords, + arguments, body, decorator_list, type_params, - range: _range, + range: _, }) => Self::ClassDef(StmtClassDef { name: name.as_str(), - bases: bases.iter().map(Into::into).collect(), - keywords: keywords.iter().map(Into::into).collect(), + arguments: arguments.as_ref().map(Into::into), body: body.iter().map(Into::into).collect(), decorator_list: decorator_list.iter().map(Into::into).collect(), - type_params: type_params.iter().map(Into::into).collect(), + type_params: type_params.as_ref().map(Into::into), }), - ast::Stmt::Return(ast::StmtReturn { - value, - range: _range, - }) => Self::Return(StmtReturn { + ast::Stmt::Return(ast::StmtReturn { value, range: _ }) => Self::Return(StmtReturn { value: value.as_ref().map(Into::into), }), - ast::Stmt::Delete(ast::StmtDelete { - targets, - range: _range, - }) => Self::Delete(StmtDelete { + ast::Stmt::Delete(ast::StmtDelete { targets, range: _ }) => Self::Delete(StmtDelete { targets: targets.iter().map(Into::into).collect(), }), ast::Stmt::TypeAlias(ast::StmtTypeAlias { - range: _range, + range: _, name, type_params, value, }) => Self::TypeAlias(StmtTypeAlias { name: name.into(), - type_params: type_params.iter().map(Into::into).collect(), + type_params: type_params.as_ref().map(Into::into), value: value.into(), }), ast::Stmt::Assign(ast::StmtAssign { targets, value, - range: _range, + range: _, }) => Self::Assign(StmtAssign { targets: targets.iter().map(Into::into).collect(), value: value.into(), @@ -1288,7 +1267,7 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { target, op, value, - range: _range, + range: _, }) => Self::AugAssign(StmtAugAssign { target: target.into(), op: (*op).into(), @@ -1299,7 +1278,7 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { annotation, value, simple, - range: _range, + range: _, }) => Self::AnnAssign(StmtAnnAssign { target: target.into(), annotation: annotation.into(), @@ -1307,24 +1286,14 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { simple: *simple, }), ast::Stmt::For(ast::StmtFor { + is_async, target, iter, body, orelse, - range: _range, + range: _, }) => Self::For(StmtFor { - target: target.into(), - iter: iter.into(), - body: body.iter().map(Into::into).collect(), - orelse: orelse.iter().map(Into::into).collect(), - }), - ast::Stmt::AsyncFor(ast::StmtAsyncFor { - target, - iter, - body, - orelse, - range: _range, - }) => Self::AsyncFor(StmtAsyncFor { + is_async: *is_async, target: target.into(), iter: iter.into(), body: body.iter().map(Into::into).collect(), @@ -1334,7 +1303,7 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { test, body, orelse, - range: _range, + range: _, }) => Self::While(StmtWhile { test: test.into(), body: body.iter().map(Into::into).collect(), @@ -1344,32 +1313,26 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { test, body, elif_else_clauses, - range: _range, + range: _, }) => Self::If(StmtIf { test: test.into(), body: body.iter().map(Into::into).collect(), elif_else_clauses: elif_else_clauses.iter().map(Into::into).collect(), }), ast::Stmt::With(ast::StmtWith { + is_async, items, body, - range: _range, + range: _, }) => Self::With(StmtWith { - items: items.iter().map(Into::into).collect(), - body: body.iter().map(Into::into).collect(), - }), - ast::Stmt::AsyncWith(ast::StmtAsyncWith { - items, - body, - range: _range, - }) => Self::AsyncWith(StmtAsyncWith { + is_async: *is_async, items: items.iter().map(Into::into).collect(), body: body.iter().map(Into::into).collect(), }), ast::Stmt::Match(ast::StmtMatch { subject, cases, - range: _range, + range: _, }) => Self::Match(StmtMatch { subject: subject.into(), cases: cases.iter().map(Into::into).collect(), @@ -1377,7 +1340,7 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { ast::Stmt::Raise(ast::StmtRaise { exc, cause, - range: _range, + range: _, }) => Self::Raise(StmtRaise { exc: exc.as_ref().map(Into::into), cause: cause.as_ref().map(Into::into), @@ -1387,73 +1350,53 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { handlers, orelse, finalbody, - range: _range, + is_star, + range: _, }) => Self::Try(StmtTry { body: body.iter().map(Into::into).collect(), handlers: handlers.iter().map(Into::into).collect(), orelse: orelse.iter().map(Into::into).collect(), finalbody: finalbody.iter().map(Into::into).collect(), - }), - ast::Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, - }) => Self::TryStar(StmtTryStar { - body: body.iter().map(Into::into).collect(), - handlers: handlers.iter().map(Into::into).collect(), - orelse: orelse.iter().map(Into::into).collect(), - finalbody: finalbody.iter().map(Into::into).collect(), + is_star: *is_star, }), ast::Stmt::Assert(ast::StmtAssert { test, msg, - range: _range, + range: _, }) => Self::Assert(StmtAssert { test: test.into(), msg: msg.as_ref().map(Into::into), }), - ast::Stmt::Import(ast::StmtImport { - names, - range: _range, - }) => Self::Import(StmtImport { + ast::Stmt::Import(ast::StmtImport { names, range: _ }) => Self::Import(StmtImport { names: names.iter().map(Into::into).collect(), }), ast::Stmt::ImportFrom(ast::StmtImportFrom { module, names, level, - range: _range, + range: _, }) => Self::ImportFrom(StmtImportFrom { module: module.as_deref(), names: names.iter().map(Into::into).collect(), level: *level, }), - ast::Stmt::Global(ast::StmtGlobal { - names, - range: _range, - }) => Self::Global(StmtGlobal { - names: names.iter().map(ast::Identifier::as_str).collect(), - }), - ast::Stmt::Nonlocal(ast::StmtNonlocal { - names, - range: _range, - }) => Self::Nonlocal(StmtNonlocal { + ast::Stmt::Global(ast::StmtGlobal { names, range: _ }) => Self::Global(StmtGlobal { names: names.iter().map(ast::Identifier::as_str).collect(), }), - ast::Stmt::LineMagic(ast::StmtLineMagic { + ast::Stmt::Nonlocal(ast::StmtNonlocal { names, range: _ }) => { + Self::Nonlocal(StmtNonlocal { + names: names.iter().map(ast::Identifier::as_str).collect(), + }) + } + ast::Stmt::IpyEscapeCommand(ast::StmtIpyEscapeCommand { kind, value, - range: _range, - }) => Self::LineMagic(StmtLineMagic { + range: _, + }) => Self::IpyEscapeCommand(StmtIpyEscapeCommand { kind: *kind, value: value.as_str(), }), - ast::Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => Self::Expr(StmtExpr { + ast::Stmt::Expr(ast::StmtExpr { value, range: _ }) => Self::Expr(StmtExpr { value: value.into(), }), ast::Stmt::Pass(_) => Self::Pass, diff --git a/crates/ruff_python_ast/src/expression.rs b/crates/ruff_python_ast/src/expression.rs new file mode 100644 index 0000000000000..c76b093faba4d --- /dev/null +++ b/crates/ruff_python_ast/src/expression.rs @@ -0,0 +1,291 @@ +use ruff_text_size::TextRange; + +use crate::node::AnyNodeRef; +use crate::{self as ast, Expr, Ranged}; + +/// Unowned pendant to [`ast::Expr`] that stores a reference instead of a owned value. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ExpressionRef<'a> { + BoolOp(&'a ast::ExprBoolOp), + NamedExpr(&'a ast::ExprNamedExpr), + BinOp(&'a ast::ExprBinOp), + UnaryOp(&'a ast::ExprUnaryOp), + Lambda(&'a ast::ExprLambda), + IfExp(&'a ast::ExprIfExp), + Dict(&'a ast::ExprDict), + Set(&'a ast::ExprSet), + ListComp(&'a ast::ExprListComp), + SetComp(&'a ast::ExprSetComp), + DictComp(&'a ast::ExprDictComp), + GeneratorExp(&'a ast::ExprGeneratorExp), + Await(&'a ast::ExprAwait), + Yield(&'a ast::ExprYield), + YieldFrom(&'a ast::ExprYieldFrom), + Compare(&'a ast::ExprCompare), + Call(&'a ast::ExprCall), + FormattedValue(&'a ast::ExprFormattedValue), + FString(&'a ast::ExprFString), + Constant(&'a ast::ExprConstant), + Attribute(&'a ast::ExprAttribute), + Subscript(&'a ast::ExprSubscript), + Starred(&'a ast::ExprStarred), + Name(&'a ast::ExprName), + List(&'a ast::ExprList), + Tuple(&'a ast::ExprTuple), + Slice(&'a ast::ExprSlice), + IpyEscapeCommand(&'a ast::ExprIpyEscapeCommand), +} + +impl<'a> From<&'a Box> for ExpressionRef<'a> { + fn from(value: &'a Box) -> Self { + ExpressionRef::from(value.as_ref()) + } +} + +impl<'a> From<&'a Expr> for ExpressionRef<'a> { + fn from(value: &'a Expr) -> Self { + match value { + Expr::BoolOp(value) => ExpressionRef::BoolOp(value), + Expr::NamedExpr(value) => ExpressionRef::NamedExpr(value), + Expr::BinOp(value) => ExpressionRef::BinOp(value), + Expr::UnaryOp(value) => ExpressionRef::UnaryOp(value), + Expr::Lambda(value) => ExpressionRef::Lambda(value), + Expr::IfExp(value) => ExpressionRef::IfExp(value), + Expr::Dict(value) => ExpressionRef::Dict(value), + Expr::Set(value) => ExpressionRef::Set(value), + Expr::ListComp(value) => ExpressionRef::ListComp(value), + Expr::SetComp(value) => ExpressionRef::SetComp(value), + Expr::DictComp(value) => ExpressionRef::DictComp(value), + Expr::GeneratorExp(value) => ExpressionRef::GeneratorExp(value), + Expr::Await(value) => ExpressionRef::Await(value), + Expr::Yield(value) => ExpressionRef::Yield(value), + Expr::YieldFrom(value) => ExpressionRef::YieldFrom(value), + Expr::Compare(value) => ExpressionRef::Compare(value), + Expr::Call(value) => ExpressionRef::Call(value), + Expr::FormattedValue(value) => ExpressionRef::FormattedValue(value), + Expr::FString(value) => ExpressionRef::FString(value), + Expr::Constant(value) => ExpressionRef::Constant(value), + Expr::Attribute(value) => ExpressionRef::Attribute(value), + Expr::Subscript(value) => ExpressionRef::Subscript(value), + Expr::Starred(value) => ExpressionRef::Starred(value), + Expr::Name(value) => ExpressionRef::Name(value), + Expr::List(value) => ExpressionRef::List(value), + Expr::Tuple(value) => ExpressionRef::Tuple(value), + Expr::Slice(value) => ExpressionRef::Slice(value), + Expr::IpyEscapeCommand(value) => ExpressionRef::IpyEscapeCommand(value), + } + } +} + +impl<'a> From<&'a ast::ExprBoolOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprBoolOp) -> Self { + Self::BoolOp(value) + } +} +impl<'a> From<&'a ast::ExprNamedExpr> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprNamedExpr) -> Self { + Self::NamedExpr(value) + } +} +impl<'a> From<&'a ast::ExprBinOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprBinOp) -> Self { + Self::BinOp(value) + } +} +impl<'a> From<&'a ast::ExprUnaryOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprUnaryOp) -> Self { + Self::UnaryOp(value) + } +} +impl<'a> From<&'a ast::ExprLambda> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprLambda) -> Self { + Self::Lambda(value) + } +} +impl<'a> From<&'a ast::ExprIfExp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprIfExp) -> Self { + Self::IfExp(value) + } +} +impl<'a> From<&'a ast::ExprDict> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprDict) -> Self { + Self::Dict(value) + } +} +impl<'a> From<&'a ast::ExprSet> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSet) -> Self { + Self::Set(value) + } +} +impl<'a> From<&'a ast::ExprListComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprListComp) -> Self { + Self::ListComp(value) + } +} +impl<'a> From<&'a ast::ExprSetComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSetComp) -> Self { + Self::SetComp(value) + } +} +impl<'a> From<&'a ast::ExprDictComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprDictComp) -> Self { + Self::DictComp(value) + } +} +impl<'a> From<&'a ast::ExprGeneratorExp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprGeneratorExp) -> Self { + Self::GeneratorExp(value) + } +} +impl<'a> From<&'a ast::ExprAwait> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprAwait) -> Self { + Self::Await(value) + } +} +impl<'a> From<&'a ast::ExprYield> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprYield) -> Self { + Self::Yield(value) + } +} +impl<'a> From<&'a ast::ExprYieldFrom> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprYieldFrom) -> Self { + Self::YieldFrom(value) + } +} +impl<'a> From<&'a ast::ExprCompare> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprCompare) -> Self { + Self::Compare(value) + } +} +impl<'a> From<&'a ast::ExprCall> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprCall) -> Self { + Self::Call(value) + } +} +impl<'a> From<&'a ast::ExprFormattedValue> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprFormattedValue) -> Self { + Self::FormattedValue(value) + } +} +impl<'a> From<&'a ast::ExprFString> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprFString) -> Self { + Self::FString(value) + } +} +impl<'a> From<&'a ast::ExprConstant> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprConstant) -> Self { + Self::Constant(value) + } +} +impl<'a> From<&'a ast::ExprAttribute> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprAttribute) -> Self { + Self::Attribute(value) + } +} +impl<'a> From<&'a ast::ExprSubscript> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSubscript) -> Self { + Self::Subscript(value) + } +} +impl<'a> From<&'a ast::ExprStarred> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprStarred) -> Self { + Self::Starred(value) + } +} +impl<'a> From<&'a ast::ExprName> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprName) -> Self { + Self::Name(value) + } +} +impl<'a> From<&'a ast::ExprList> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprList) -> Self { + Self::List(value) + } +} +impl<'a> From<&'a ast::ExprTuple> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprTuple) -> Self { + Self::Tuple(value) + } +} +impl<'a> From<&'a ast::ExprSlice> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSlice) -> Self { + Self::Slice(value) + } +} +impl<'a> From<&'a ast::ExprIpyEscapeCommand> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprIpyEscapeCommand) -> Self { + Self::IpyEscapeCommand(value) + } +} + +impl<'a> From> for AnyNodeRef<'a> { + fn from(value: ExpressionRef<'a>) -> Self { + match value { + ExpressionRef::BoolOp(expression) => AnyNodeRef::ExprBoolOp(expression), + ExpressionRef::NamedExpr(expression) => AnyNodeRef::ExprNamedExpr(expression), + ExpressionRef::BinOp(expression) => AnyNodeRef::ExprBinOp(expression), + ExpressionRef::UnaryOp(expression) => AnyNodeRef::ExprUnaryOp(expression), + ExpressionRef::Lambda(expression) => AnyNodeRef::ExprLambda(expression), + ExpressionRef::IfExp(expression) => AnyNodeRef::ExprIfExp(expression), + ExpressionRef::Dict(expression) => AnyNodeRef::ExprDict(expression), + ExpressionRef::Set(expression) => AnyNodeRef::ExprSet(expression), + ExpressionRef::ListComp(expression) => AnyNodeRef::ExprListComp(expression), + ExpressionRef::SetComp(expression) => AnyNodeRef::ExprSetComp(expression), + ExpressionRef::DictComp(expression) => AnyNodeRef::ExprDictComp(expression), + ExpressionRef::GeneratorExp(expression) => AnyNodeRef::ExprGeneratorExp(expression), + ExpressionRef::Await(expression) => AnyNodeRef::ExprAwait(expression), + ExpressionRef::Yield(expression) => AnyNodeRef::ExprYield(expression), + ExpressionRef::YieldFrom(expression) => AnyNodeRef::ExprYieldFrom(expression), + ExpressionRef::Compare(expression) => AnyNodeRef::ExprCompare(expression), + ExpressionRef::Call(expression) => AnyNodeRef::ExprCall(expression), + ExpressionRef::FormattedValue(expression) => AnyNodeRef::ExprFormattedValue(expression), + ExpressionRef::FString(expression) => AnyNodeRef::ExprFString(expression), + ExpressionRef::Constant(expression) => AnyNodeRef::ExprConstant(expression), + ExpressionRef::Attribute(expression) => AnyNodeRef::ExprAttribute(expression), + ExpressionRef::Subscript(expression) => AnyNodeRef::ExprSubscript(expression), + ExpressionRef::Starred(expression) => AnyNodeRef::ExprStarred(expression), + ExpressionRef::Name(expression) => AnyNodeRef::ExprName(expression), + ExpressionRef::List(expression) => AnyNodeRef::ExprList(expression), + ExpressionRef::Tuple(expression) => AnyNodeRef::ExprTuple(expression), + ExpressionRef::Slice(expression) => AnyNodeRef::ExprSlice(expression), + ExpressionRef::IpyEscapeCommand(expression) => { + AnyNodeRef::ExprIpyEscapeCommand(expression) + } + } + } +} + +impl Ranged for ExpressionRef<'_> { + fn range(&self) -> TextRange { + match self { + ExpressionRef::BoolOp(expression) => expression.range(), + ExpressionRef::NamedExpr(expression) => expression.range(), + ExpressionRef::BinOp(expression) => expression.range(), + ExpressionRef::UnaryOp(expression) => expression.range(), + ExpressionRef::Lambda(expression) => expression.range(), + ExpressionRef::IfExp(expression) => expression.range(), + ExpressionRef::Dict(expression) => expression.range(), + ExpressionRef::Set(expression) => expression.range(), + ExpressionRef::ListComp(expression) => expression.range(), + ExpressionRef::SetComp(expression) => expression.range(), + ExpressionRef::DictComp(expression) => expression.range(), + ExpressionRef::GeneratorExp(expression) => expression.range(), + ExpressionRef::Await(expression) => expression.range(), + ExpressionRef::Yield(expression) => expression.range(), + ExpressionRef::YieldFrom(expression) => expression.range(), + ExpressionRef::Compare(expression) => expression.range(), + ExpressionRef::Call(expression) => expression.range(), + ExpressionRef::FormattedValue(expression) => expression.range(), + ExpressionRef::FString(expression) => expression.range(), + ExpressionRef::Constant(expression) => expression.range(), + ExpressionRef::Attribute(expression) => expression.range(), + ExpressionRef::Subscript(expression) => expression.range(), + ExpressionRef::Starred(expression) => expression.range(), + ExpressionRef::Name(expression) => expression.range(), + ExpressionRef::List(expression) => expression.range(), + ExpressionRef::Tuple(expression) => expression.range(), + ExpressionRef::Slice(expression) => expression.range(), + ExpressionRef::IpyEscapeCommand(expression) => expression.range(), + } + } +} diff --git a/crates/ruff_python_ast/src/function.rs b/crates/ruff_python_ast/src/function.rs deleted file mode 100644 index 11deb8d773459..0000000000000 --- a/crates/ruff_python_ast/src/function.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::node::AnyNodeRef; -use crate::{ - Arguments, Decorator, Expr, Identifier, Ranged, StmtAsyncFunctionDef, StmtFunctionDef, Suite, -}; -use ruff_text_size::TextRange; - -/// Enum that represents any python function definition. -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AnyFunctionDefinition<'a> { - FunctionDefinition(&'a StmtFunctionDef), - AsyncFunctionDefinition(&'a StmtAsyncFunctionDef), -} - -impl<'a> AnyFunctionDefinition<'a> { - pub const fn cast_ref(reference: AnyNodeRef<'a>) -> Option { - match reference { - AnyNodeRef::StmtAsyncFunctionDef(definition) => { - Some(Self::AsyncFunctionDefinition(definition)) - } - AnyNodeRef::StmtFunctionDef(definition) => Some(Self::FunctionDefinition(definition)), - _ => None, - } - } - - /// Returns `Some` if this is a [`StmtFunctionDef`] and `None` otherwise. - pub const fn as_function_definition(self) -> Option<&'a StmtFunctionDef> { - if let Self::FunctionDefinition(definition) = self { - Some(definition) - } else { - None - } - } - - /// Returns `Some` if this is a [`StmtAsyncFunctionDef`] and `None` otherwise. - pub const fn as_async_function_definition(self) -> Option<&'a StmtAsyncFunctionDef> { - if let Self::AsyncFunctionDefinition(definition) = self { - Some(definition) - } else { - None - } - } - - /// Returns the function's name - pub const fn name(self) -> &'a Identifier { - match self { - Self::FunctionDefinition(definition) => &definition.name, - Self::AsyncFunctionDefinition(definition) => &definition.name, - } - } - - /// Returns the function arguments (parameters). - pub fn arguments(self) -> &'a Arguments { - match self { - Self::FunctionDefinition(definition) => definition.args.as_ref(), - Self::AsyncFunctionDefinition(definition) => definition.args.as_ref(), - } - } - - /// Returns the function's body - pub const fn body(self) -> &'a Suite { - match self { - Self::FunctionDefinition(definition) => &definition.body, - Self::AsyncFunctionDefinition(definition) => &definition.body, - } - } - - /// Returns the decorators attributing the function. - pub fn decorators(self) -> &'a [Decorator] { - match self { - Self::FunctionDefinition(definition) => &definition.decorator_list, - Self::AsyncFunctionDefinition(definition) => &definition.decorator_list, - } - } - - pub fn returns(self) -> Option<&'a Expr> { - match self { - Self::FunctionDefinition(definition) => definition.returns.as_deref(), - Self::AsyncFunctionDefinition(definition) => definition.returns.as_deref(), - } - } - - /// Returns `true` if this is [`Self::AsyncFunctionDefinition`] - pub const fn is_async(self) -> bool { - matches!(self, Self::AsyncFunctionDefinition(_)) - } -} - -impl Ranged for AnyFunctionDefinition<'_> { - fn range(&self) -> TextRange { - match self { - AnyFunctionDefinition::FunctionDefinition(definition) => definition.range(), - AnyFunctionDefinition::AsyncFunctionDefinition(definition) => definition.range(), - } - } -} - -impl<'a> From<&'a StmtFunctionDef> for AnyFunctionDefinition<'a> { - fn from(value: &'a StmtFunctionDef) -> Self { - Self::FunctionDefinition(value) - } -} - -impl<'a> From<&'a StmtAsyncFunctionDef> for AnyFunctionDefinition<'a> { - fn from(value: &'a StmtAsyncFunctionDef) -> Self { - Self::AsyncFunctionDefinition(value) - } -} - -impl<'a> From> for AnyNodeRef<'a> { - fn from(value: AnyFunctionDefinition<'a>) -> Self { - match value { - AnyFunctionDefinition::FunctionDefinition(function_def) => { - AnyNodeRef::StmtFunctionDef(function_def) - } - AnyFunctionDefinition::AsyncFunctionDefinition(async_def) => { - AnyNodeRef::StmtAsyncFunctionDef(async_def) - } - } - } -} - -impl<'a> From<&'a AnyFunctionDefinition<'a>> for AnyNodeRef<'a> { - fn from(value: &'a AnyFunctionDefinition<'a>) -> Self { - (*value).into() - } -} diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index 923c73269933b..ad97566880a80 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -1,33 +1,30 @@ use std::borrow::Cow; use std::path::Path; -use crate::{ - self as ast, Arguments, Constant, ExceptHandler, Expr, Keyword, MatchCase, Pattern, Ranged, - Stmt, TypeParam, -}; use num_traits::Zero; -use ruff_text_size::TextRange; use smallvec::SmallVec; +use ruff_text_size::TextRange; + use crate::call_path::CallPath; use crate::statement_visitor::{walk_body, walk_stmt, StatementVisitor}; +use crate::{ + self as ast, Arguments, Constant, ExceptHandler, Expr, MatchCase, Pattern, Ranged, Stmt, + TypeParam, +}; /// Return `true` if the `Stmt` is a compound statement (as opposed to a simple statement). pub const fn is_compound_statement(stmt: &Stmt) -> bool { matches!( stmt, Stmt::FunctionDef(_) - | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) | Stmt::While(_) | Stmt::For(_) - | Stmt::AsyncFor(_) | Stmt::Match(_) | Stmt::With(_) - | Stmt::AsyncWith(_) | Stmt::If(_) | Stmt::Try(_) - | Stmt::TryStar(_) ) } @@ -50,9 +47,8 @@ where // Accept empty initializers. if let Expr::Call(ast::ExprCall { func, - args, - keywords, - range: _range, + arguments: Arguments { args, keywords, .. }, + range: _, }) = expr { // Ex) `list()` @@ -71,7 +67,7 @@ where if !matches!( left.as_ref(), Expr::Constant(_) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::List(_) | Expr::Tuple(_) | Expr::Set(_) @@ -85,7 +81,7 @@ where if !matches!( right.as_ref(), Expr::Constant(_) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::List(_) | Expr::Tuple(_) | Expr::Set(_) @@ -111,6 +107,7 @@ where | Expr::Subscript(_) | Expr::Yield(_) | Expr::YieldFrom(_) + | Expr::IpyEscapeCommand(_) ) }) } @@ -125,19 +122,14 @@ where return true; } match expr { - Expr::BoolOp(ast::ExprBoolOp { - values, - range: _range, - .. - }) - | Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => values.iter().any(|expr| any_over_expr(expr, func)), + Expr::BoolOp(ast::ExprBoolOp { values, .. }) + | Expr::FString(ast::ExprFString { values, .. }) => { + values.iter().any(|expr| any_over_expr(expr, func)) + } Expr::NamedExpr(ast::ExprNamedExpr { target, value, - range: _range, + range: _, }) => any_over_expr(target, func) || any_over_expr(value, func), Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { any_over_expr(left, func) || any_over_expr(right, func) @@ -148,44 +140,35 @@ where test, body, orelse, - range: _range, + range: _, }) => any_over_expr(test, func) || any_over_expr(body, func) || any_over_expr(orelse, func), Expr::Dict(ast::ExprDict { keys, values, - range: _range, + range: _, }) => values .iter() .chain(keys.iter().flatten()) .any(|expr| any_over_expr(expr, func)), - Expr::Set(ast::ExprSet { - elts, - range: _range, - }) - | Expr::List(ast::ExprList { - elts, - range: _range, - .. - }) - | Expr::Tuple(ast::ExprTuple { - elts, - range: _range, - .. - }) => elts.iter().any(|expr| any_over_expr(expr, func)), + Expr::Set(ast::ExprSet { elts, range: _ }) + | Expr::List(ast::ExprList { elts, range: _, .. }) + | Expr::Tuple(ast::ExprTuple { elts, range: _, .. }) => { + elts.iter().any(|expr| any_over_expr(expr, func)) + } Expr::ListComp(ast::ExprListComp { elt, generators, - range: _range, + range: _, }) | Expr::SetComp(ast::ExprSetComp { elt, generators, - range: _range, + range: _, }) | Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, - range: _range, + range: _, }) => { any_over_expr(elt, func) || generators.iter().any(|generator| { @@ -198,7 +181,7 @@ where key, value, generators, - range: _range, + range: _, }) => { any_over_expr(key, func) || any_over_expr(value, func) @@ -208,38 +191,24 @@ where || generator.ifs.iter().any(|expr| any_over_expr(expr, func)) }) } - Expr::Await(ast::ExprAwait { - value, - range: _range, - }) - | Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) + Expr::Await(ast::ExprAwait { value, range: _ }) + | Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) | Expr::Attribute(ast::ExprAttribute { - value, - range: _range, - .. + value, range: _, .. }) | Expr::Starred(ast::ExprStarred { - value, - range: _range, - .. + value, range: _, .. }) => any_over_expr(value, func), - Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => value + Expr::Yield(ast::ExprYield { value, range: _ }) => value .as_ref() - .map_or(false, |value| any_over_expr(value, func)), + .is_some_and(|value| any_over_expr(value, func)), Expr::Compare(ast::ExprCompare { left, comparators, .. }) => any_over_expr(left, func) || comparators.iter().any(|expr| any_over_expr(expr, func)), Expr::Call(ast::ExprCall { func: call_func, - args, - keywords, - range: _range, + arguments: Arguments { args, keywords, .. }, + range: _, }) => { any_over_expr(call_func, func) || args.iter().any(|expr| any_over_expr(expr, func)) @@ -253,7 +222,7 @@ where any_over_expr(value, func) || format_spec .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) } Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { any_over_expr(value, func) || any_over_expr(slice, func) @@ -262,20 +231,20 @@ where lower, upper, step, - range: _range, + range: _, }) => { lower .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) || upper .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) || step .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) } Expr::Name(_) | Expr::Constant(_) => false, - Expr::LineMagic(_) => false, + Expr::IpyEscapeCommand(_) => false, } } @@ -286,7 +255,7 @@ where match type_param { TypeParam::TypeVar(ast::TypeParamTypeVar { bound, .. }) => bound .as_ref() - .map_or(false, |value| any_over_expr(value, func)), + .is_some_and(|value| any_over_expr(value, func)), TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { .. }) => false, TypeParam::ParamSpec(ast::TypeParamParamSpec { .. }) => false, } @@ -297,15 +266,11 @@ where F: Fn(&Expr) -> bool, { match pattern { - Pattern::MatchValue(ast::PatternMatchValue { - value, - range: _range, - }) => any_over_expr(value, func), + Pattern::MatchValue(ast::PatternMatchValue { value, range: _ }) => { + any_over_expr(value, func) + } Pattern::MatchSingleton(_) => false, - Pattern::MatchSequence(ast::PatternMatchSequence { - patterns, - range: _range, - }) => patterns + Pattern::MatchSequence(ast::PatternMatchSequence { patterns, range: _ }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, func)), Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => { @@ -331,11 +296,8 @@ where Pattern::MatchStar(_) => false, Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => pattern .as_ref() - .map_or(false, |pattern| any_over_pattern(pattern, func)), - Pattern::MatchOr(ast::PatternMatchOr { - patterns, - range: _range, - }) => patterns + .is_some_and(|pattern| any_over_pattern(pattern, func)), + Pattern::MatchOr(ast::PatternMatchOr { patterns, range: _ }) => patterns .iter() .any(|pattern| any_over_pattern(pattern, func)), } @@ -347,42 +309,44 @@ where { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { - args, - body, - decorator_list, - returns, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - args, + parameters, + type_params, body, decorator_list, returns, .. }) => { - args.posonlyargs + parameters + .posonlyargs .iter() - .chain(args.args.iter().chain(args.kwonlyargs.iter())) - .any(|arg_with_default| { - arg_with_default + .chain(parameters.args.iter().chain(parameters.kwonlyargs.iter())) + .any(|parameter| { + parameter .default .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) - || arg_with_default - .def + .is_some_and(|expr| any_over_expr(expr, func)) + || parameter + .parameter .annotation .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + .is_some_and(|expr| any_over_expr(expr, func)) }) - || args.vararg.as_ref().map_or(false, |arg| { - arg.annotation + || parameters.vararg.as_ref().is_some_and(|parameter| { + parameter + .annotation .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + .is_some_and(|expr| any_over_expr(expr, func)) }) - || args.kwarg.as_ref().map_or(false, |arg| { - arg.annotation + || parameters.kwarg.as_ref().is_some_and(|parameter| { + parameter + .annotation .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + .is_some_and(|expr| any_over_expr(expr, func)) + }) + || type_params.as_ref().is_some_and(|type_params| { + type_params + .iter() + .any(|type_param| any_over_type_param(type_param, func)) }) || body.iter().any(|stmt| any_over_stmt(stmt, func)) || decorator_list @@ -390,34 +354,39 @@ where .any(|decorator| any_over_expr(&decorator.expression, func)) || returns .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) } Stmt::ClassDef(ast::StmtClassDef { - bases, - keywords, + arguments, + type_params, body, decorator_list, .. }) => { - bases.iter().any(|expr| any_over_expr(expr, func)) - || keywords - .iter() - .any(|keyword| any_over_expr(&keyword.value, func)) + arguments + .as_deref() + .is_some_and(|Arguments { args, keywords, .. }| { + args.iter().any(|expr| any_over_expr(expr, func)) + || keywords + .iter() + .any(|keyword| any_over_expr(&keyword.value, func)) + }) + || type_params.as_ref().is_some_and(|type_params| { + type_params + .iter() + .any(|type_param| any_over_type_param(type_param, func)) + }) || body.iter().any(|stmt| any_over_stmt(stmt, func)) || decorator_list .iter() .any(|decorator| any_over_expr(&decorator.expression, func)) } - Stmt::Return(ast::StmtReturn { - value, - range: _range, - }) => value + Stmt::Return(ast::StmtReturn { value, range: _ }) => value .as_ref() - .map_or(false, |value| any_over_expr(value, func)), - Stmt::Delete(ast::StmtDelete { - targets, - range: _range, - }) => targets.iter().any(|expr| any_over_expr(expr, func)), + .is_some_and(|value| any_over_expr(value, func)), + Stmt::Delete(ast::StmtDelete { targets, range: _ }) => { + targets.iter().any(|expr| any_over_expr(expr, func)) + } Stmt::TypeAlias(ast::StmtTypeAlias { name, type_params, @@ -425,9 +394,11 @@ where .. }) => { any_over_expr(name, func) - || type_params - .iter() - .any(|type_param| any_over_type_param(type_param, func)) + || type_params.as_ref().is_some_and(|type_params| { + type_params + .iter() + .any(|type_param| any_over_type_param(type_param, func)) + }) || any_over_expr(value, func) } Stmt::Assign(ast::StmtAssign { targets, value, .. }) => { @@ -446,7 +417,7 @@ where || any_over_expr(annotation, func) || value .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) } Stmt::For(ast::StmtFor { target, @@ -454,13 +425,6 @@ where body, orelse, .. - }) - | Stmt::AsyncFor(ast::StmtAsyncFor { - target, - iter, - body, - orelse, - .. }) => { any_over_expr(target, func) || any_over_expr(iter, func) @@ -471,13 +435,13 @@ where test, body, orelse, - range: _range, + range: _, }) => any_over_expr(test, func) || any_over_body(body, func) || any_over_body(orelse, func), Stmt::If(ast::StmtIf { test, body, elif_else_clauses, - range: _range, + range: _, }) => { any_over_expr(test, func) || any_over_body(body, func) @@ -485,44 +449,36 @@ where clause .test .as_ref() - .map_or(false, |test| any_over_expr(test, func)) + .is_some_and(|test| any_over_expr(test, func)) || any_over_body(&clause.body, func) }) } - Stmt::With(ast::StmtWith { items, body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { items, body, .. }) => { items.iter().any(|with_item| { any_over_expr(&with_item.context_expr, func) || with_item .optional_vars .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + .is_some_and(|expr| any_over_expr(expr, func)) }) || any_over_body(body, func) } Stmt::Raise(ast::StmtRaise { exc, cause, - range: _range, + range: _, }) => { - exc.as_ref() - .map_or(false, |value| any_over_expr(value, func)) + exc.as_ref().is_some_and(|value| any_over_expr(value, func)) || cause .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + .is_some_and(|value| any_over_expr(value, func)) } Stmt::Try(ast::StmtTry { body, handlers, orelse, finalbody, - range: _range, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, + is_star: _, + range: _, }) => { any_over_body(body, func) || handlers.iter().any(|handler| { @@ -531,9 +487,7 @@ where body, .. }) = handler; - type_ - .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + type_.as_ref().is_some_and(|expr| any_over_expr(expr, func)) || any_over_body(body, func) }) || any_over_body(orelse, func) @@ -542,17 +496,15 @@ where Stmt::Assert(ast::StmtAssert { test, msg, - range: _range, + range: _, }) => { any_over_expr(test, func) - || msg - .as_ref() - .map_or(false, |value| any_over_expr(value, func)) + || msg.as_ref().is_some_and(|value| any_over_expr(value, func)) } Stmt::Match(ast::StmtMatch { subject, cases, - range: _range, + range: _, }) => { any_over_expr(subject, func) || cases.iter().any(|case| { @@ -560,12 +512,10 @@ where pattern, guard, body, - range: _range, + range: _, } = case; any_over_pattern(pattern, func) - || guard - .as_ref() - .map_or(false, |expr| any_over_expr(expr, func)) + || guard.as_ref().is_some_and(|expr| any_over_expr(expr, func)) || any_over_body(body, func) }) } @@ -573,12 +523,9 @@ where Stmt::ImportFrom(_) => false, Stmt::Global(_) => false, Stmt::Nonlocal(_) => false, - Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => any_over_expr(value, func), + Stmt::Expr(ast::StmtExpr { value, range: _ }) => any_over_expr(value, func), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => false, - Stmt::LineMagic(_) => false, + Stmt::IpyEscapeCommand(_) => false, } } @@ -642,15 +589,6 @@ pub fn is_constant_non_singleton(expr: &Expr) -> bool { is_constant(expr) && !is_singleton(expr) } -/// Return the [`Keyword`] with the given name, if it's present in the list of -/// [`Keyword`] arguments. -pub fn find_keyword<'a>(keywords: &'a [Keyword], keyword_name: &str) -> Option<&'a Keyword> { - keywords.iter().find(|keyword| { - let Keyword { arg, .. } = keyword; - arg.as_ref().map_or(false, |arg| arg == keyword_name) - }) -} - /// Return `true` if an [`Expr`] is `None`. pub const fn is_const_none(expr: &Expr) -> bool { matches!( @@ -687,14 +625,6 @@ pub const fn is_const_false(expr: &Expr) -> bool { ) } -/// Return `true` if a keyword argument is present with a non-`None` value. -pub fn has_non_none_keyword(keywords: &[Keyword], keyword: &str) -> bool { - find_keyword(keywords, keyword).map_or(false, |keyword| { - let Keyword { value, .. } = keyword; - !is_const_none(value) - }) -} - /// Extract the names of all handled exceptions. pub fn extract_handled_exceptions(handlers: &[ExceptHandler]) -> Vec<&Expr> { let mut handled_exceptions = Vec::new(); @@ -716,30 +646,6 @@ pub fn extract_handled_exceptions(handlers: &[ExceptHandler]) -> Vec<&Expr> { handled_exceptions } -/// Returns `true` if the given name is included in the given [`Arguments`]. -pub fn includes_arg_name(name: &str, arguments: &Arguments) -> bool { - if arguments - .posonlyargs - .iter() - .chain(&arguments.args) - .chain(&arguments.kwonlyargs) - .any(|arg| arg.def.arg.as_str() == name) - { - return true; - } - if let Some(arg) = &arguments.vararg { - if arg.arg.as_str() == name { - return true; - } - } - if let Some(arg) = &arguments.kwarg { - if arg.arg.as_str() == name { - return true; - } - } - false -} - /// Given an [`Expr`] that can be callable or not (like a decorator, which could /// be used with or without explicit call syntax), return the underlying /// callable. @@ -856,42 +762,81 @@ pub fn to_module_path(package: &Path, path: &Path) -> Option> { .collect::>>() } -/// Create a [`CallPath`] from a relative import reference name (like `".foo.bar"`). -/// -/// Returns an empty [`CallPath`] if the import is invalid (e.g., a relative import that -/// extends beyond the top-level module). +/// Format the call path for a relative import. /// /// # Examples /// /// ```rust -/// # use smallvec::{smallvec, SmallVec}; -/// # use ruff_python_ast::helpers::from_relative_import; +/// # use ruff_python_ast::helpers::collect_import_from_member; /// -/// assert_eq!(from_relative_import(&[], "bar"), SmallVec::from_buf(["bar"])); -/// assert_eq!(from_relative_import(&["foo".to_string()], "bar"), SmallVec::from_buf(["foo", "bar"])); -/// assert_eq!(from_relative_import(&["foo".to_string()], "bar.baz"), SmallVec::from_buf(["foo", "bar", "baz"])); -/// assert_eq!(from_relative_import(&["foo".to_string()], ".bar"), SmallVec::from_buf(["bar"])); -/// assert!(from_relative_import(&["foo".to_string()], "..bar").is_empty()); -/// assert!(from_relative_import(&["foo".to_string()], "...bar").is_empty()); +/// assert_eq!(collect_import_from_member(None, None, "bar").as_slice(), ["bar"]); +/// assert_eq!(collect_import_from_member(Some(1), None, "bar").as_slice(), [".", "bar"]); +/// assert_eq!(collect_import_from_member(Some(1), Some("foo"), "bar").as_slice(), [".", "foo", "bar"]); /// ``` -pub fn from_relative_import<'a>(module: &'a [String], name: &'a str) -> CallPath<'a> { - let mut call_path: CallPath = SmallVec::with_capacity(module.len() + 1); +pub fn collect_import_from_member<'a>( + level: Option, + module: Option<&'a str>, + member: &'a str, +) -> CallPath<'a> { + let mut call_path: CallPath = SmallVec::with_capacity( + level.unwrap_or_default() as usize + + module + .map(|module| module.split('.').count()) + .unwrap_or_default() + + 1, + ); + + // Include the dots as standalone segments. + if let Some(level) = level { + if level > 0 { + for _ in 0..level { + call_path.push("."); + } + } + } + + // Add the remaining segments. + if let Some(module) = module { + call_path.extend(module.split('.')); + } + + // Add the member. + call_path.push(member); + + call_path +} + +/// Format the call path for a relative import, or `None` if the relative import extends beyond +/// the root module. +pub fn from_relative_import<'a>( + // The path from which the import is relative. + module: &'a [String], + // The path of the import itself (e.g., given `from ..foo import bar`, `[".", ".", "foo", "bar]`). + import: &[&'a str], + // The remaining segments to the call path (e.g., given `bar.baz`, `["baz"]`). + tail: &[&'a str], +) -> Option> { + let mut call_path: CallPath = SmallVec::with_capacity(module.len() + import.len() + tail.len()); // Start with the module path. call_path.extend(module.iter().map(String::as_str)); // Remove segments based on the number of dots. - for _ in 0..name.chars().take_while(|c| *c == '.').count() { - if call_path.is_empty() { - return SmallVec::new(); + for segment in import { + if *segment == "." { + if call_path.is_empty() { + return None; + } + call_path.pop(); + } else { + call_path.push(segment); } - call_path.pop(); } // Add the remaining segments. - call_path.extend(name.trim_start_matches('.').split('.')); + call_path.extend_from_slice(tail); - call_path + Some(call_path) } /// Given an imported module (based on its relative import level and module name), return the @@ -939,7 +884,7 @@ where { fn visit_stmt(&mut self, stmt: &'b Stmt) { match stmt { - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } Stmt::Return(stmt) => self.returns.push(stmt), @@ -963,16 +908,12 @@ where Stmt::Raise(ast::StmtRaise { exc, cause, - range: _range, + range: _, }) => { self.raises .push((stmt.range(), exc.as_deref(), cause.as_deref())); } - Stmt::ClassDef(_) - | Stmt::FunctionDef(_) - | Stmt::AsyncFunctionDef(_) - | Stmt::Try(_) - | Stmt::TryStar(_) => {} + Stmt::ClassDef(_) | Stmt::FunctionDef(_) | Stmt::Try(_) => {} Stmt::If(ast::StmtIf { body, elif_else_clauses, @@ -985,9 +926,7 @@ where } Stmt::While(ast::StmtWhile { body, .. }) | Stmt::With(ast::StmtWith { body, .. }) - | Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) - | Stmt::For(ast::StmtFor { body, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, .. }) => { + | Stmt::For(ast::StmtFor { body, .. }) => { walk_body(self, body); } Stmt::Match(ast::StmtMatch { cases, .. }) => { @@ -1002,11 +941,7 @@ where /// Return `true` if a `Stmt` is a docstring. pub fn is_docstring_stmt(stmt: &Stmt) -> bool { - if let Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) = stmt - { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { matches!( value.as_ref(), Expr::Constant(ast::ExprConstant { @@ -1019,75 +954,13 @@ pub fn is_docstring_stmt(stmt: &Stmt) -> bool { } } -/// A representation of a function call's positional and keyword arguments that ignores -/// starred expressions. -#[derive(Default)] -pub struct CallArguments<'a> { - args: &'a [Expr], - keywords: &'a [Keyword], -} - -impl<'a> CallArguments<'a> { - pub fn new(args: &'a [Expr], keywords: &'a [Keyword]) -> Self { - Self { args, keywords } - } - - /// Get the argument with the given name or position, or `None` if no such - /// argument exists. - pub fn argument(&self, name: &str, position: usize) -> Option<&'a Expr> { - self.keywords - .iter() - .find(|keyword| { - let Keyword { arg, .. } = keyword; - arg.as_ref().map_or(false, |arg| arg == name) - }) - .map(|keyword| &keyword.value) - .or_else(|| { - self.args - .iter() - .take_while(|expr| !expr.is_starred_expr()) - .nth(position) - }) - } - - /// Return the number of arguments. - pub fn len(&self) -> usize { - self.args.len() + self.keywords.len() - } - - /// Return `true` if there are no arguments. - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Return the number of positional arguments. - pub fn num_args(&self) -> usize { - self.args - .iter() - .take_while(|expr| !expr.is_starred_expr()) - .count() - } - - /// Return the number of keyword arguments. - pub fn num_kwargs(&self) -> usize { - self.keywords - .iter() - .filter(|keyword| keyword.arg.is_some()) - .count() - } -} - /// Check if a node is part of a conditional branch. pub fn on_conditional_branch<'a>(parents: &mut impl Iterator) -> bool { parents.any(|parent| { if matches!(parent, Stmt::If(_) | Stmt::While(_) | Stmt::Match(_)) { return true; } - if let Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) = parent - { + if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = parent { if value.is_if_exp_expr() { return true; } @@ -1101,7 +974,7 @@ pub fn in_nested_block<'a>(mut parents: impl Iterator) -> bool parents.any(|parent| { matches!( parent, - Stmt::Try(_) | Stmt::TryStar(_) | Stmt::If(_) | Stmt::With(_) | Stmt::Match(_) + Stmt::Try(_) | Stmt::If(_) | Stmt::With(_) | Stmt::Match(_) ) }) } @@ -1205,58 +1078,40 @@ impl Truthiness { Expr::Constant(ast::ExprConstant { value, .. }) => match value { Constant::Bool(value) => Some(*value), Constant::None => Some(false), - Constant::Str(string) => Some(!string.is_empty()), + Constant::Str(ast::StringConstant { value, .. }) => Some(!value.is_empty()), Constant::Bytes(bytes) => Some(!bytes.is_empty()), Constant::Int(int) => Some(!int.is_zero()), Constant::Float(float) => Some(*float != 0.0), Constant::Complex { real, imag } => Some(*real != 0.0 || *imag != 0.0), Constant::Ellipsis => Some(true), }, - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { + Expr::FString(ast::ExprFString { values, .. }) => { if values.is_empty() { Some(false) } else if values.iter().any(|value| { - let Expr::Constant(ast::ExprConstant { - value: Constant::Str(string), + if let Expr::Constant(ast::ExprConstant { + value: Constant::Str(ast::StringConstant { value, .. }), .. }) = &value - else { - return false; - }; - !string.is_empty() + { + !value.is_empty() + } else { + false + } }) { Some(true) } else { None } } - Expr::List(ast::ExprList { - elts, - range: _range, - .. - }) - | Expr::Set(ast::ExprSet { - elts, - range: _range, - }) - | Expr::Tuple(ast::ExprTuple { - elts, - range: _range, - .. - }) => Some(!elts.is_empty()), - Expr::Dict(ast::ExprDict { - keys, - range: _range, - .. - }) => Some(!keys.is_empty()), + Expr::List(ast::ExprList { elts, .. }) + | Expr::Set(ast::ExprSet { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) => Some(!elts.is_empty()), + Expr::Dict(ast::ExprDict { keys, .. }) => Some(!keys.is_empty()), Expr::Call(ast::ExprCall { func, - args, - keywords, - range: _range, + arguments: Arguments { args, keywords, .. }, + .. }) => { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if is_iterable_initializer(id.as_str(), |id| is_builtin(id)) { @@ -1288,13 +1143,13 @@ mod tests { use std::cell::RefCell; use std::vec; - use crate::{ - Constant, Expr, ExprConstant, ExprContext, ExprName, Identifier, Stmt, StmtTypeAlias, - TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, - }; use ruff_text_size::TextRange; use crate::helpers::{any_over_stmt, any_over_type_param, resolve_imported_module_path}; + use crate::{ + Constant, Expr, ExprConstant, ExprContext, ExprName, Identifier, Stmt, StmtTypeAlias, + TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, + }; #[test] fn resolve_import() { @@ -1368,7 +1223,10 @@ mod tests { }); let type_alias = Stmt::TypeAlias(StmtTypeAlias { name: Box::new(name.clone()), - type_params: vec![type_var_one, type_var_two], + type_params: Some(TypeParams { + type_params: vec![type_var_one, type_var_two], + range: TextRange::default(), + }), value: Box::new(constant_three.clone()), range: TextRange::default(), }); diff --git a/crates/ruff_python_ast/src/identifier.rs b/crates/ruff_python_ast/src/identifier.rs index 888b4c9d0fbf6..2ff690ebc88a6 100644 --- a/crates/ruff_python_ast/src/identifier.rs +++ b/crates/ruff_python_ast/src/identifier.rs @@ -10,7 +10,7 @@ //! //! This module can be used to identify the [`TextRange`] of the `except` token. -use crate::{self as ast, Alias, Arg, ArgWithDefault, ExceptHandler, Ranged, Stmt}; +use crate::{self as ast, Alias, ExceptHandler, Parameter, ParameterWithDefault, Ranged, Stmt}; use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_python_trivia::{is_python_whitespace, Cursor}; @@ -20,6 +20,32 @@ pub trait Identifier { fn identifier(&self) -> TextRange; } +impl Identifier for ast::StmtFunctionDef { + /// Return the [`TextRange`] of the identifier in the given function definition. + /// + /// For example, return the range of `f` in: + /// ```python + /// def f(): + /// ... + /// ``` + fn identifier(&self) -> TextRange { + self.name.range() + } +} + +impl Identifier for ast::StmtClassDef { + /// Return the [`TextRange`] of the identifier in the given class definition. + /// + /// For example, return the range of `C` in: + /// ```python + /// class C(): + /// ... + /// ``` + fn identifier(&self) -> TextRange { + self.name.range() + } +} + impl Identifier for Stmt { /// Return the [`TextRange`] of the identifier in the given statement. /// @@ -30,16 +56,15 @@ impl Identifier for Stmt { /// ``` fn identifier(&self) -> TextRange { match self { - Stmt::ClassDef(ast::StmtClassDef { name, .. }) - | Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => name.range(), + Stmt::ClassDef(class) => class.identifier(), + Stmt::FunctionDef(function) => function.identifier(), _ => self.range(), } } } -impl Identifier for Arg { - /// Return the [`TextRange`] for the identifier defining an [`Arg`]. +impl Identifier for Parameter { + /// Return the [`TextRange`] for the identifier defining an [`Parameter`]. /// /// For example, return the range of `x` in: /// ```python @@ -47,12 +72,12 @@ impl Identifier for Arg { /// ... /// ``` fn identifier(&self) -> TextRange { - self.arg.range() + self.name.range() } } -impl Identifier for ArgWithDefault { - /// Return the [`TextRange`] for the identifier defining an [`ArgWithDefault`]. +impl Identifier for ParameterWithDefault { + /// Return the [`TextRange`] for the identifier defining an [`ParameterWithDefault`]. /// /// For example, return the range of `x` in: /// ```python @@ -60,7 +85,7 @@ impl Identifier for ArgWithDefault { /// ... /// ``` fn identifier(&self) -> TextRange { - self.def.identifier() + self.parameter.identifier() } } @@ -85,10 +110,9 @@ pub fn except(handler: &ExceptHandler, source: &str) -> TextRange { .expect("Failed to find `except` token in `ExceptHandler`") } -/// Return the [`TextRange`] of the `else` token in a `For`, `AsyncFor`, or `While` statement. +/// Return the [`TextRange`] of the `else` token in a `For` or `While` statement. pub fn else_(stmt: &Stmt, source: &str) -> Option { let (Stmt::For(ast::StmtFor { body, orelse, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) | Stmt::While(ast::StmtWhile { body, orelse, .. })) = stmt else { return None; diff --git a/crates/ruff_python_ast/src/lib.rs b/crates/ruff_python_ast/src/lib.rs index 4b8b9a1eeb92e..8f8a5ad4f2ce1 100644 --- a/crates/ruff_python_ast/src/lib.rs +++ b/crates/ruff_python_ast/src/lib.rs @@ -1,17 +1,18 @@ use ruff_text_size::{TextRange, TextSize}; +use std::path::Path; pub mod all; pub mod call_path; -pub mod cast; pub mod comparable; pub mod docstrings; -pub mod function; +mod expression; pub mod hashable; pub mod helpers; pub mod identifier; pub mod imports; pub mod node; mod nodes; +pub mod parenthesize; pub mod relocate; pub mod statement_visitor; pub mod stmt_if; @@ -21,6 +22,7 @@ pub mod types; pub mod visitor; pub mod whitespace; +pub use expression::*; pub use nodes::*; pub trait Ranged { @@ -49,3 +51,36 @@ where T::range(self) } } + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum PySourceType { + #[default] + Python, + Stub, + Ipynb, +} + +impl PySourceType { + pub const fn is_python(&self) -> bool { + matches!(self, PySourceType::Python) + } + + pub const fn is_stub(&self) -> bool { + matches!(self, PySourceType::Stub) + } + + pub const fn is_ipynb(&self) -> bool { + matches!(self, PySourceType::Ipynb) + } +} + +impl From<&Path> for PySourceType { + fn from(path: &Path) -> Self { + match path.extension() { + Some(ext) if ext == "pyi" => PySourceType::Stub, + Some(ext) if ext == "ipynb" => PySourceType::Ipynb, + _ => PySourceType::Python, + } + } +} diff --git a/crates/ruff_python_ast/src/node.rs b/crates/ruff_python_ast/src/node.rs index 9890c31b58faf..b565f86c26b49 100644 --- a/crates/ruff_python_ast/src/node.rs +++ b/crates/ruff_python_ast/src/node.rs @@ -1,7 +1,8 @@ +use crate::visitor::preorder::PreorderVisitor; use crate::{ - self as ast, Alias, Arg, ArgWithDefault, Arguments, Comprehension, Decorator, ExceptHandler, - Expr, Keyword, MatchCase, Mod, Pattern, Ranged, Stmt, TypeParam, TypeParamParamSpec, - TypeParamTypeVar, TypeParamTypeVarTuple, WithItem, + self as ast, Alias, Arguments, Comprehension, Decorator, ExceptHandler, Expr, Keyword, + MatchCase, Mod, Parameter, ParameterWithDefault, Parameters, Pattern, Ranged, Stmt, TypeParam, + TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, WithItem, }; use ruff_text_size::TextRange; use std::ptr::NonNull; @@ -17,6 +18,10 @@ pub trait AstNode: Ranged { /// Consumes `self` and returns its [`AnyNode`] representation. fn into_any_node(self) -> AnyNode; + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized; } #[derive(Clone, Debug, is_macro::Is, PartialEq)] @@ -24,7 +29,6 @@ pub enum AnyNode { ModModule(ast::ModModule), ModExpression(ast::ModExpression), StmtFunctionDef(ast::StmtFunctionDef), - StmtAsyncFunctionDef(ast::StmtAsyncFunctionDef), StmtClassDef(ast::StmtClassDef), StmtReturn(ast::StmtReturn), StmtDelete(ast::StmtDelete), @@ -33,15 +37,12 @@ pub enum AnyNode { StmtAugAssign(ast::StmtAugAssign), StmtAnnAssign(ast::StmtAnnAssign), StmtFor(ast::StmtFor), - StmtAsyncFor(ast::StmtAsyncFor), StmtWhile(ast::StmtWhile), StmtIf(ast::StmtIf), StmtWith(ast::StmtWith), - StmtAsyncWith(ast::StmtAsyncWith), StmtMatch(ast::StmtMatch), StmtRaise(ast::StmtRaise), StmtTry(ast::StmtTry), - StmtTryStar(ast::StmtTryStar), StmtAssert(ast::StmtAssert), StmtImport(ast::StmtImport), StmtImportFrom(ast::StmtImportFrom), @@ -51,7 +52,7 @@ pub enum AnyNode { StmtPass(ast::StmtPass), StmtBreak(ast::StmtBreak), StmtContinue(ast::StmtContinue), - StmtLineMagic(ast::StmtLineMagic), + StmtIpyEscapeCommand(ast::StmtIpyEscapeCommand), ExprBoolOp(ast::ExprBoolOp), ExprNamedExpr(ast::ExprNamedExpr), ExprBinOp(ast::ExprBinOp), @@ -70,7 +71,7 @@ pub enum AnyNode { ExprCompare(ast::ExprCompare), ExprCall(ast::ExprCall), ExprFormattedValue(ast::ExprFormattedValue), - ExprJoinedStr(ast::ExprJoinedStr), + ExprFString(ast::ExprFString), ExprConstant(ast::ExprConstant), ExprAttribute(ast::ExprAttribute), ExprSubscript(ast::ExprSubscript), @@ -79,7 +80,7 @@ pub enum AnyNode { ExprList(ast::ExprList), ExprTuple(ast::ExprTuple), ExprSlice(ast::ExprSlice), - ExprLineMagic(ast::ExprLineMagic), + ExprIpyEscapeCommand(ast::ExprIpyEscapeCommand), ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler), PatternMatchValue(ast::PatternMatchValue), PatternMatchSingleton(ast::PatternMatchSingleton), @@ -91,24 +92,25 @@ pub enum AnyNode { PatternMatchOr(ast::PatternMatchOr), Comprehension(Comprehension), Arguments(Arguments), - Arg(Arg), - ArgWithDefault(ArgWithDefault), + Parameters(Parameters), + Parameter(Parameter), + ParameterWithDefault(ParameterWithDefault), Keyword(Keyword), Alias(Alias), WithItem(WithItem), MatchCase(MatchCase), Decorator(Decorator), ElifElseClause(ast::ElifElseClause), - TypeParamTypeVar(ast::TypeParamTypeVar), - TypeParamTypeVarTuple(ast::TypeParamTypeVarTuple), - TypeParamParamSpec(ast::TypeParamParamSpec), + TypeParams(TypeParams), + TypeParamTypeVar(TypeParamTypeVar), + TypeParamTypeVarTuple(TypeParamTypeVarTuple), + TypeParamParamSpec(TypeParamParamSpec), } impl AnyNode { pub fn statement(self) -> Option { match self { AnyNode::StmtFunctionDef(node) => Some(Stmt::FunctionDef(node)), - AnyNode::StmtAsyncFunctionDef(node) => Some(Stmt::AsyncFunctionDef(node)), AnyNode::StmtClassDef(node) => Some(Stmt::ClassDef(node)), AnyNode::StmtReturn(node) => Some(Stmt::Return(node)), AnyNode::StmtDelete(node) => Some(Stmt::Delete(node)), @@ -117,15 +119,12 @@ impl AnyNode { AnyNode::StmtAugAssign(node) => Some(Stmt::AugAssign(node)), AnyNode::StmtAnnAssign(node) => Some(Stmt::AnnAssign(node)), AnyNode::StmtFor(node) => Some(Stmt::For(node)), - AnyNode::StmtAsyncFor(node) => Some(Stmt::AsyncFor(node)), AnyNode::StmtWhile(node) => Some(Stmt::While(node)), AnyNode::StmtIf(node) => Some(Stmt::If(node)), AnyNode::StmtWith(node) => Some(Stmt::With(node)), - AnyNode::StmtAsyncWith(node) => Some(Stmt::AsyncWith(node)), AnyNode::StmtMatch(node) => Some(Stmt::Match(node)), AnyNode::StmtRaise(node) => Some(Stmt::Raise(node)), AnyNode::StmtTry(node) => Some(Stmt::Try(node)), - AnyNode::StmtTryStar(node) => Some(Stmt::TryStar(node)), AnyNode::StmtAssert(node) => Some(Stmt::Assert(node)), AnyNode::StmtImport(node) => Some(Stmt::Import(node)), AnyNode::StmtImportFrom(node) => Some(Stmt::ImportFrom(node)), @@ -135,7 +134,7 @@ impl AnyNode { AnyNode::StmtPass(node) => Some(Stmt::Pass(node)), AnyNode::StmtBreak(node) => Some(Stmt::Break(node)), AnyNode::StmtContinue(node) => Some(Stmt::Continue(node)), - AnyNode::StmtLineMagic(node) => Some(Stmt::LineMagic(node)), + AnyNode::StmtIpyEscapeCommand(node) => Some(Stmt::IpyEscapeCommand(node)), AnyNode::ModModule(_) | AnyNode::ModExpression(_) @@ -157,7 +156,7 @@ impl AnyNode { | AnyNode::ExprCompare(_) | AnyNode::ExprCall(_) | AnyNode::ExprFormattedValue(_) - | AnyNode::ExprJoinedStr(_) + | AnyNode::ExprFString(_) | AnyNode::ExprConstant(_) | AnyNode::ExprAttribute(_) | AnyNode::ExprSubscript(_) @@ -166,7 +165,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) - | AnyNode::ExprLineMagic(_) + | AnyNode::ExprIpyEscapeCommand(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -178,13 +177,15 @@ impl AnyNode { | AnyNode::PatternMatchOr(_) | AnyNode::Comprehension(_) | AnyNode::Arguments(_) - | AnyNode::Arg(_) - | AnyNode::ArgWithDefault(_) + | AnyNode::Parameters(_) + | AnyNode::Parameter(_) + | AnyNode::ParameterWithDefault(_) | AnyNode::Keyword(_) | AnyNode::Alias(_) | AnyNode::WithItem(_) | AnyNode::MatchCase(_) | AnyNode::Decorator(_) + | AnyNode::TypeParams(_) | AnyNode::TypeParamTypeVar(_) | AnyNode::TypeParamTypeVarTuple(_) | AnyNode::TypeParamParamSpec(_) @@ -212,7 +213,7 @@ impl AnyNode { AnyNode::ExprCompare(node) => Some(Expr::Compare(node)), AnyNode::ExprCall(node) => Some(Expr::Call(node)), AnyNode::ExprFormattedValue(node) => Some(Expr::FormattedValue(node)), - AnyNode::ExprJoinedStr(node) => Some(Expr::JoinedStr(node)), + AnyNode::ExprFString(node) => Some(Expr::FString(node)), AnyNode::ExprConstant(node) => Some(Expr::Constant(node)), AnyNode::ExprAttribute(node) => Some(Expr::Attribute(node)), AnyNode::ExprSubscript(node) => Some(Expr::Subscript(node)), @@ -221,12 +222,11 @@ impl AnyNode { AnyNode::ExprList(node) => Some(Expr::List(node)), AnyNode::ExprTuple(node) => Some(Expr::Tuple(node)), AnyNode::ExprSlice(node) => Some(Expr::Slice(node)), - AnyNode::ExprLineMagic(node) => Some(Expr::LineMagic(node)), + AnyNode::ExprIpyEscapeCommand(node) => Some(Expr::IpyEscapeCommand(node)), AnyNode::ModModule(_) | AnyNode::ModExpression(_) | AnyNode::StmtFunctionDef(_) - | AnyNode::StmtAsyncFunctionDef(_) | AnyNode::StmtClassDef(_) | AnyNode::StmtReturn(_) | AnyNode::StmtDelete(_) @@ -235,15 +235,12 @@ impl AnyNode { | AnyNode::StmtAugAssign(_) | AnyNode::StmtAnnAssign(_) | AnyNode::StmtFor(_) - | AnyNode::StmtAsyncFor(_) | AnyNode::StmtWhile(_) | AnyNode::StmtIf(_) | AnyNode::StmtWith(_) - | AnyNode::StmtAsyncWith(_) | AnyNode::StmtMatch(_) | AnyNode::StmtRaise(_) | AnyNode::StmtTry(_) - | AnyNode::StmtTryStar(_) | AnyNode::StmtAssert(_) | AnyNode::StmtImport(_) | AnyNode::StmtImportFrom(_) @@ -253,7 +250,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) - | AnyNode::StmtLineMagic(_) + | AnyNode::StmtIpyEscapeCommand(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -265,13 +262,15 @@ impl AnyNode { | AnyNode::PatternMatchOr(_) | AnyNode::Comprehension(_) | AnyNode::Arguments(_) - | AnyNode::Arg(_) - | AnyNode::ArgWithDefault(_) + | AnyNode::Parameters(_) + | AnyNode::Parameter(_) + | AnyNode::ParameterWithDefault(_) | AnyNode::Keyword(_) | AnyNode::Alias(_) | AnyNode::WithItem(_) | AnyNode::MatchCase(_) | AnyNode::Decorator(_) + | AnyNode::TypeParams(_) | AnyNode::TypeParamTypeVar(_) | AnyNode::TypeParamTypeVarTuple(_) | AnyNode::TypeParamParamSpec(_) @@ -285,7 +284,6 @@ impl AnyNode { AnyNode::ModExpression(node) => Some(Mod::Expression(node)), AnyNode::StmtFunctionDef(_) - | AnyNode::StmtAsyncFunctionDef(_) | AnyNode::StmtClassDef(_) | AnyNode::StmtReturn(_) | AnyNode::StmtDelete(_) @@ -294,15 +292,12 @@ impl AnyNode { | AnyNode::StmtAugAssign(_) | AnyNode::StmtAnnAssign(_) | AnyNode::StmtFor(_) - | AnyNode::StmtAsyncFor(_) | AnyNode::StmtWhile(_) | AnyNode::StmtIf(_) | AnyNode::StmtWith(_) - | AnyNode::StmtAsyncWith(_) | AnyNode::StmtMatch(_) | AnyNode::StmtRaise(_) | AnyNode::StmtTry(_) - | AnyNode::StmtTryStar(_) | AnyNode::StmtAssert(_) | AnyNode::StmtImport(_) | AnyNode::StmtImportFrom(_) @@ -312,7 +307,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) - | AnyNode::StmtLineMagic(_) + | AnyNode::StmtIpyEscapeCommand(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -331,7 +326,7 @@ impl AnyNode { | AnyNode::ExprCompare(_) | AnyNode::ExprCall(_) | AnyNode::ExprFormattedValue(_) - | AnyNode::ExprJoinedStr(_) + | AnyNode::ExprFString(_) | AnyNode::ExprConstant(_) | AnyNode::ExprAttribute(_) | AnyNode::ExprSubscript(_) @@ -340,7 +335,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) - | AnyNode::ExprLineMagic(_) + | AnyNode::ExprIpyEscapeCommand(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -352,13 +347,15 @@ impl AnyNode { | AnyNode::PatternMatchOr(_) | AnyNode::Comprehension(_) | AnyNode::Arguments(_) - | AnyNode::Arg(_) - | AnyNode::ArgWithDefault(_) + | AnyNode::Parameters(_) + | AnyNode::Parameter(_) + | AnyNode::ParameterWithDefault(_) | AnyNode::Keyword(_) | AnyNode::Alias(_) | AnyNode::WithItem(_) | AnyNode::MatchCase(_) | AnyNode::Decorator(_) + | AnyNode::TypeParams(_) | AnyNode::TypeParamTypeVar(_) | AnyNode::TypeParamTypeVarTuple(_) | AnyNode::TypeParamParamSpec(_) @@ -380,7 +377,6 @@ impl AnyNode { AnyNode::ModModule(_) | AnyNode::ModExpression(_) | AnyNode::StmtFunctionDef(_) - | AnyNode::StmtAsyncFunctionDef(_) | AnyNode::StmtClassDef(_) | AnyNode::StmtReturn(_) | AnyNode::StmtDelete(_) @@ -389,15 +385,12 @@ impl AnyNode { | AnyNode::StmtAugAssign(_) | AnyNode::StmtAnnAssign(_) | AnyNode::StmtFor(_) - | AnyNode::StmtAsyncFor(_) | AnyNode::StmtWhile(_) | AnyNode::StmtIf(_) | AnyNode::StmtWith(_) - | AnyNode::StmtAsyncWith(_) | AnyNode::StmtMatch(_) | AnyNode::StmtRaise(_) | AnyNode::StmtTry(_) - | AnyNode::StmtTryStar(_) | AnyNode::StmtAssert(_) | AnyNode::StmtImport(_) | AnyNode::StmtImportFrom(_) @@ -407,7 +400,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) - | AnyNode::StmtLineMagic(_) + | AnyNode::StmtIpyEscapeCommand(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -426,7 +419,7 @@ impl AnyNode { | AnyNode::ExprCompare(_) | AnyNode::ExprCall(_) | AnyNode::ExprFormattedValue(_) - | AnyNode::ExprJoinedStr(_) + | AnyNode::ExprFString(_) | AnyNode::ExprConstant(_) | AnyNode::ExprAttribute(_) | AnyNode::ExprSubscript(_) @@ -435,17 +428,19 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) - | AnyNode::ExprLineMagic(_) + | AnyNode::ExprIpyEscapeCommand(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::Comprehension(_) | AnyNode::Arguments(_) - | AnyNode::Arg(_) - | AnyNode::ArgWithDefault(_) + | AnyNode::Parameters(_) + | AnyNode::Parameter(_) + | AnyNode::ParameterWithDefault(_) | AnyNode::Keyword(_) | AnyNode::Alias(_) | AnyNode::WithItem(_) | AnyNode::MatchCase(_) | AnyNode::Decorator(_) + | AnyNode::TypeParams(_) | AnyNode::TypeParamTypeVar(_) | AnyNode::TypeParamTypeVarTuple(_) | AnyNode::TypeParamParamSpec(_) @@ -460,7 +455,6 @@ impl AnyNode { AnyNode::ModModule(_) | AnyNode::ModExpression(_) | AnyNode::StmtFunctionDef(_) - | AnyNode::StmtAsyncFunctionDef(_) | AnyNode::StmtClassDef(_) | AnyNode::StmtReturn(_) | AnyNode::StmtDelete(_) @@ -469,15 +463,12 @@ impl AnyNode { | AnyNode::StmtAugAssign(_) | AnyNode::StmtAnnAssign(_) | AnyNode::StmtFor(_) - | AnyNode::StmtAsyncFor(_) | AnyNode::StmtWhile(_) | AnyNode::StmtIf(_) | AnyNode::StmtWith(_) - | AnyNode::StmtAsyncWith(_) | AnyNode::StmtMatch(_) | AnyNode::StmtRaise(_) | AnyNode::StmtTry(_) - | AnyNode::StmtTryStar(_) | AnyNode::StmtAssert(_) | AnyNode::StmtImport(_) | AnyNode::StmtImportFrom(_) @@ -487,7 +478,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) - | AnyNode::StmtLineMagic(_) + | AnyNode::StmtIpyEscapeCommand(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -506,7 +497,7 @@ impl AnyNode { | AnyNode::ExprCompare(_) | AnyNode::ExprCall(_) | AnyNode::ExprFormattedValue(_) - | AnyNode::ExprJoinedStr(_) + | AnyNode::ExprFString(_) | AnyNode::ExprConstant(_) | AnyNode::ExprAttribute(_) | AnyNode::ExprSubscript(_) @@ -515,7 +506,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) - | AnyNode::ExprLineMagic(_) + | AnyNode::ExprIpyEscapeCommand(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSequence(_) @@ -526,13 +517,15 @@ impl AnyNode { | AnyNode::PatternMatchOr(_) | AnyNode::Comprehension(_) | AnyNode::Arguments(_) - | AnyNode::Arg(_) - | AnyNode::ArgWithDefault(_) + | AnyNode::Parameters(_) + | AnyNode::Parameter(_) + | AnyNode::ParameterWithDefault(_) | AnyNode::Keyword(_) | AnyNode::Alias(_) | AnyNode::WithItem(_) | AnyNode::MatchCase(_) | AnyNode::Decorator(_) + | AnyNode::TypeParams(_) | AnyNode::TypeParamTypeVar(_) | AnyNode::TypeParamTypeVarTuple(_) | AnyNode::TypeParamParamSpec(_) @@ -565,7 +558,6 @@ impl AnyNode { Self::ModModule(node) => AnyNodeRef::ModModule(node), Self::ModExpression(node) => AnyNodeRef::ModExpression(node), Self::StmtFunctionDef(node) => AnyNodeRef::StmtFunctionDef(node), - Self::StmtAsyncFunctionDef(node) => AnyNodeRef::StmtAsyncFunctionDef(node), Self::StmtClassDef(node) => AnyNodeRef::StmtClassDef(node), Self::StmtReturn(node) => AnyNodeRef::StmtReturn(node), Self::StmtDelete(node) => AnyNodeRef::StmtDelete(node), @@ -574,15 +566,12 @@ impl AnyNode { Self::StmtAugAssign(node) => AnyNodeRef::StmtAugAssign(node), Self::StmtAnnAssign(node) => AnyNodeRef::StmtAnnAssign(node), Self::StmtFor(node) => AnyNodeRef::StmtFor(node), - Self::StmtAsyncFor(node) => AnyNodeRef::StmtAsyncFor(node), Self::StmtWhile(node) => AnyNodeRef::StmtWhile(node), Self::StmtIf(node) => AnyNodeRef::StmtIf(node), Self::StmtWith(node) => AnyNodeRef::StmtWith(node), - Self::StmtAsyncWith(node) => AnyNodeRef::StmtAsyncWith(node), Self::StmtMatch(node) => AnyNodeRef::StmtMatch(node), Self::StmtRaise(node) => AnyNodeRef::StmtRaise(node), Self::StmtTry(node) => AnyNodeRef::StmtTry(node), - Self::StmtTryStar(node) => AnyNodeRef::StmtTryStar(node), Self::StmtAssert(node) => AnyNodeRef::StmtAssert(node), Self::StmtImport(node) => AnyNodeRef::StmtImport(node), Self::StmtImportFrom(node) => AnyNodeRef::StmtImportFrom(node), @@ -592,7 +581,7 @@ impl AnyNode { Self::StmtPass(node) => AnyNodeRef::StmtPass(node), Self::StmtBreak(node) => AnyNodeRef::StmtBreak(node), Self::StmtContinue(node) => AnyNodeRef::StmtContinue(node), - Self::StmtLineMagic(node) => AnyNodeRef::StmtLineMagic(node), + Self::StmtIpyEscapeCommand(node) => AnyNodeRef::StmtIpyEscapeCommand(node), Self::ExprBoolOp(node) => AnyNodeRef::ExprBoolOp(node), Self::ExprNamedExpr(node) => AnyNodeRef::ExprNamedExpr(node), Self::ExprBinOp(node) => AnyNodeRef::ExprBinOp(node), @@ -611,7 +600,7 @@ impl AnyNode { Self::ExprCompare(node) => AnyNodeRef::ExprCompare(node), Self::ExprCall(node) => AnyNodeRef::ExprCall(node), Self::ExprFormattedValue(node) => AnyNodeRef::ExprFormattedValue(node), - Self::ExprJoinedStr(node) => AnyNodeRef::ExprJoinedStr(node), + Self::ExprFString(node) => AnyNodeRef::ExprFString(node), Self::ExprConstant(node) => AnyNodeRef::ExprConstant(node), Self::ExprAttribute(node) => AnyNodeRef::ExprAttribute(node), Self::ExprSubscript(node) => AnyNodeRef::ExprSubscript(node), @@ -620,7 +609,7 @@ impl AnyNode { Self::ExprList(node) => AnyNodeRef::ExprList(node), Self::ExprTuple(node) => AnyNodeRef::ExprTuple(node), Self::ExprSlice(node) => AnyNodeRef::ExprSlice(node), - Self::ExprLineMagic(node) => AnyNodeRef::ExprLineMagic(node), + Self::ExprIpyEscapeCommand(node) => AnyNodeRef::ExprIpyEscapeCommand(node), Self::ExceptHandlerExceptHandler(node) => AnyNodeRef::ExceptHandlerExceptHandler(node), Self::PatternMatchValue(node) => AnyNodeRef::PatternMatchValue(node), Self::PatternMatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node), @@ -632,13 +621,15 @@ impl AnyNode { Self::PatternMatchOr(node) => AnyNodeRef::PatternMatchOr(node), Self::Comprehension(node) => AnyNodeRef::Comprehension(node), Self::Arguments(node) => AnyNodeRef::Arguments(node), - Self::Arg(node) => AnyNodeRef::Arg(node), - Self::ArgWithDefault(node) => AnyNodeRef::ArgWithDefault(node), + Self::Parameters(node) => AnyNodeRef::Parameters(node), + Self::Parameter(node) => AnyNodeRef::Parameter(node), + Self::ParameterWithDefault(node) => AnyNodeRef::ParameterWithDefault(node), Self::Keyword(node) => AnyNodeRef::Keyword(node), Self::Alias(node) => AnyNodeRef::Alias(node), Self::WithItem(node) => AnyNodeRef::WithItem(node), Self::MatchCase(node) => AnyNodeRef::MatchCase(node), Self::Decorator(node) => AnyNodeRef::Decorator(node), + Self::TypeParams(node) => AnyNodeRef::TypeParams(node), Self::TypeParamTypeVar(node) => AnyNodeRef::TypeParamTypeVar(node), Self::TypeParamTypeVarTuple(node) => AnyNodeRef::TypeParamTypeVarTuple(node), Self::TypeParamParamSpec(node) => AnyNodeRef::TypeParamParamSpec(node), @@ -679,7 +670,16 @@ impl AstNode for ast::ModModule { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ModModule { body, range: _ } = self; + visitor.visit_body(body); + } } + impl AstNode for ast::ModExpression { fn cast(kind: AnyNode) -> Option where @@ -707,6 +707,14 @@ impl AstNode for ast::ModExpression { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ModExpression { body, range: _ } = self; + visitor.visit_expr(body); + } } impl AstNode for ast::StmtFunctionDef { fn cast(kind: AnyNode) -> Option @@ -735,33 +743,35 @@ impl AstNode for ast::StmtFunctionDef { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } -} -impl AstNode for ast::StmtAsyncFunctionDef { - fn cast(kind: AnyNode) -> Option + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) where - Self: Sized, + V: PreorderVisitor<'a> + ?Sized, { - if let AnyNode::StmtAsyncFunctionDef(node) = kind { - Some(node) - } else { - None + let ast::StmtFunctionDef { + parameters, + body, + decorator_list, + returns, + type_params, + .. + } = self; + + for decorator in decorator_list { + visitor.visit_decorator(decorator); } - } - fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::StmtAsyncFunctionDef(node) = kind { - Some(node) - } else { - None + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); } - } - fn as_any_node_ref(&self) -> AnyNodeRef { - AnyNodeRef::from(self) - } + visitor.visit_parameters(parameters); - fn into_any_node(self) -> AnyNode { - AnyNode::from(self) + for expr in returns { + visitor.visit_annotation(expr); + } + + visitor.visit_body(body); } } impl AstNode for ast::StmtClassDef { @@ -791,6 +801,33 @@ impl AstNode for ast::StmtClassDef { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtClassDef { + arguments, + body, + decorator_list, + type_params, + .. + } = self; + + for decorator in decorator_list { + visitor.visit_decorator(decorator); + } + + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + + if let Some(arguments) = arguments { + visitor.visit_arguments(arguments); + } + + visitor.visit_body(body); + } } impl AstNode for ast::StmtReturn { fn cast(kind: AnyNode) -> Option @@ -819,6 +856,16 @@ impl AstNode for ast::StmtReturn { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtReturn { value, range: _ } = self; + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtDelete { fn cast(kind: AnyNode) -> Option @@ -847,6 +894,16 @@ impl AstNode for ast::StmtDelete { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtDelete { targets, range: _ } = self; + for expr in targets { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtTypeAlias { fn cast(kind: AnyNode) -> Option @@ -875,6 +932,24 @@ impl AstNode for ast::StmtTypeAlias { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtTypeAlias { + range: _, + name, + type_params, + value, + } = self; + + visitor.visit_expr(name); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAssign { fn cast(kind: AnyNode) -> Option @@ -903,6 +978,23 @@ impl AstNode for ast::StmtAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAssign { + targets, + value, + range: _, + } = self; + + for expr in targets { + visitor.visit_expr(expr); + } + + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAugAssign { fn cast(kind: AnyNode) -> Option @@ -931,6 +1023,22 @@ impl AstNode for ast::StmtAugAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAugAssign { + target, + op, + value, + range: _, + } = self; + + visitor.visit_expr(target); + visitor.visit_operator(op); + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAnnAssign { fn cast(kind: AnyNode) -> Option @@ -959,6 +1067,25 @@ impl AstNode for ast::StmtAnnAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAnnAssign { + target, + annotation, + value, + range: _, + simple: _, + } = self; + + visitor.visit_expr(target); + visitor.visit_annotation(annotation); + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtFor { fn cast(kind: AnyNode) -> Option @@ -987,33 +1114,23 @@ impl AstNode for ast::StmtFor { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } -} -impl AstNode for ast::StmtAsyncFor { - fn cast(kind: AnyNode) -> Option + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) where - Self: Sized, + V: PreorderVisitor<'a> + ?Sized, { - if let AnyNode::StmtAsyncFor(node) = kind { - Some(node) - } else { - None - } - } - - fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::StmtAsyncFor(node) = kind { - Some(node) - } else { - None - } - } - - fn as_any_node_ref(&self) -> AnyNodeRef { - AnyNodeRef::from(self) - } + let ast::StmtFor { + target, + iter, + body, + orelse, + .. + } = self; - fn into_any_node(self) -> AnyNode { - AnyNode::from(self) + visitor.visit_expr(target); + visitor.visit_expr(iter); + visitor.visit_body(body); + visitor.visit_body(orelse); } } impl AstNode for ast::StmtWhile { @@ -1043,6 +1160,22 @@ impl AstNode for ast::StmtWhile { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtWhile { + test, + body, + orelse, + range: _, + } = self; + + visitor.visit_expr(test); + visitor.visit_body(body); + visitor.visit_body(orelse); + } } impl AstNode for ast::StmtIf { fn cast(kind: AnyNode) -> Option @@ -1071,6 +1204,24 @@ impl AstNode for ast::StmtIf { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtIf { + test, + body, + elif_else_clauses, + range: _, + } = self; + + visitor.visit_expr(test); + visitor.visit_body(body); + for clause in elif_else_clauses { + visitor.visit_elif_else_clause(clause); + } + } } impl AstNode for ast::ElifElseClause { fn cast(kind: AnyNode) -> Option @@ -1099,6 +1250,21 @@ impl AstNode for ast::ElifElseClause { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ElifElseClause { + range: _, + test, + body, + } = self; + if let Some(test) = test { + visitor.visit_expr(test); + } + visitor.visit_body(body); + } } impl AstNode for ast::StmtWith { fn cast(kind: AnyNode) -> Option @@ -1127,33 +1293,22 @@ impl AstNode for ast::StmtWith { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } -} -impl AstNode for ast::StmtAsyncWith { - fn cast(kind: AnyNode) -> Option + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) where - Self: Sized, + V: PreorderVisitor<'a> + ?Sized, { - if let AnyNode::StmtAsyncWith(node) = kind { - Some(node) - } else { - None - } - } + let ast::StmtWith { + items, + body, + is_async: _, + range: _, + } = self; - fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::StmtAsyncWith(node) = kind { - Some(node) - } else { - None + for with_item in items { + visitor.visit_with_item(with_item); } - } - - fn as_any_node_ref(&self) -> AnyNodeRef { - AnyNodeRef::from(self) - } - - fn into_any_node(self) -> AnyNode { - AnyNode::from(self) + visitor.visit_body(body); } } impl AstNode for ast::StmtMatch { @@ -1183,6 +1338,22 @@ impl AstNode for ast::StmtMatch { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtMatch { + subject, + cases, + range: _, + } = self; + + visitor.visit_expr(subject); + for match_case in cases { + visitor.visit_match_case(match_case); + } + } } impl AstNode for ast::StmtRaise { fn cast(kind: AnyNode) -> Option @@ -1211,6 +1382,24 @@ impl AstNode for ast::StmtRaise { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtRaise { + exc, + cause, + range: _, + } = self; + + if let Some(expr) = exc { + visitor.visit_expr(expr); + }; + if let Some(expr) = cause { + visitor.visit_expr(expr); + }; + } } impl AstNode for ast::StmtTry { fn cast(kind: AnyNode) -> Option @@ -1239,33 +1428,26 @@ impl AstNode for ast::StmtTry { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } -} -impl AstNode for ast::StmtTryStar { - fn cast(kind: AnyNode) -> Option + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) where - Self: Sized, + V: PreorderVisitor<'a> + ?Sized, { - if let AnyNode::StmtTryStar(node) = kind { - Some(node) - } else { - None - } - } + let ast::StmtTry { + body, + handlers, + orelse, + finalbody, + is_star: _, + range: _, + } = self; - fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::StmtTryStar(node) = kind { - Some(node) - } else { - None + visitor.visit_body(body); + for except_handler in handlers { + visitor.visit_except_handler(except_handler); } - } - - fn as_any_node_ref(&self) -> AnyNodeRef { - AnyNodeRef::from(self) - } - - fn into_any_node(self) -> AnyNode { - AnyNode::from(self) + visitor.visit_body(orelse); + visitor.visit_body(finalbody); } } impl AstNode for ast::StmtAssert { @@ -1295,6 +1477,21 @@ impl AstNode for ast::StmtAssert { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAssert { + test, + msg, + range: _, + } = self; + visitor.visit_expr(test); + if let Some(expr) = msg { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtImport { fn cast(kind: AnyNode) -> Option @@ -1323,6 +1520,17 @@ impl AstNode for ast::StmtImport { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtImport { names, range: _ } = self; + + for alias in names { + visitor.visit_alias(alias); + } + } } impl AstNode for ast::StmtImportFrom { fn cast(kind: AnyNode) -> Option @@ -1351,6 +1559,22 @@ impl AstNode for ast::StmtImportFrom { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtImportFrom { + range: _, + module: _, + names, + level: _, + } = self; + + for alias in names { + visitor.visit_alias(alias); + } + } } impl AstNode for ast::StmtGlobal { fn cast(kind: AnyNode) -> Option @@ -1379,6 +1603,13 @@ impl AstNode for ast::StmtGlobal { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtNonlocal { fn cast(kind: AnyNode) -> Option @@ -1407,6 +1638,13 @@ impl AstNode for ast::StmtNonlocal { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtExpr { fn cast(kind: AnyNode) -> Option @@ -1435,6 +1673,15 @@ impl AstNode for ast::StmtExpr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtExpr { value, range: _ } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::StmtPass { fn cast(kind: AnyNode) -> Option @@ -1463,6 +1710,13 @@ impl AstNode for ast::StmtPass { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtBreak { fn cast(kind: AnyNode) -> Option @@ -1491,6 +1745,13 @@ impl AstNode for ast::StmtBreak { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtContinue { fn cast(kind: AnyNode) -> Option @@ -1519,13 +1780,20 @@ impl AstNode for ast::StmtContinue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } -impl AstNode for ast::StmtLineMagic { +impl AstNode for ast::StmtIpyEscapeCommand { fn cast(kind: AnyNode) -> Option where Self: Sized, { - if let AnyNode::StmtLineMagic(node) = kind { + if let AnyNode::StmtIpyEscapeCommand(node) = kind { Some(node) } else { None @@ -1533,7 +1801,7 @@ impl AstNode for ast::StmtLineMagic { } fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::StmtLineMagic(node) = kind { + if let AnyNodeRef::StmtIpyEscapeCommand(node) = kind { Some(node) } else { None @@ -1547,6 +1815,13 @@ impl AstNode for ast::StmtLineMagic { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::ExprBoolOp { fn cast(kind: AnyNode) -> Option @@ -1575,6 +1850,29 @@ impl AstNode for ast::ExprBoolOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprBoolOp { + op, + values, + range: _, + } = self; + match values.as_slice() { + [left, rest @ ..] => { + visitor.visit_expr(left); + visitor.visit_bool_op(op); + for expr in rest { + visitor.visit_expr(expr); + } + } + [] => { + visitor.visit_bool_op(op); + } + } + } } impl AstNode for ast::ExprNamedExpr { fn cast(kind: AnyNode) -> Option @@ -1603,6 +1901,19 @@ impl AstNode for ast::ExprNamedExpr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprNamedExpr { + target, + value, + range: _, + } = self; + visitor.visit_expr(target); + visitor.visit_expr(value); + } } impl AstNode for ast::ExprBinOp { fn cast(kind: AnyNode) -> Option @@ -1631,6 +1942,21 @@ impl AstNode for ast::ExprBinOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprBinOp { + left, + op, + right, + range: _, + } = self; + visitor.visit_expr(left); + visitor.visit_operator(op); + visitor.visit_expr(right); + } } impl AstNode for ast::ExprUnaryOp { fn cast(kind: AnyNode) -> Option @@ -1659,6 +1985,20 @@ impl AstNode for ast::ExprUnaryOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprUnaryOp { + op, + operand, + range: _, + } = self; + + visitor.visit_unary_op(op); + visitor.visit_expr(operand); + } } impl AstNode for ast::ExprLambda { fn cast(kind: AnyNode) -> Option @@ -1687,6 +2027,22 @@ impl AstNode for ast::ExprLambda { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprLambda { + parameters, + body, + range: _, + } = self; + + if let Some(parameters) = parameters { + visitor.visit_parameters(parameters); + } + visitor.visit_expr(body); + } } impl AstNode for ast::ExprIfExp { fn cast(kind: AnyNode) -> Option @@ -1715,6 +2071,23 @@ impl AstNode for ast::ExprIfExp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprIfExp { + test, + body, + orelse, + range: _, + } = self; + + // `body if test else orelse` + visitor.visit_expr(body); + visitor.visit_expr(test); + visitor.visit_expr(orelse); + } } impl AstNode for ast::ExprDict { fn cast(kind: AnyNode) -> Option @@ -1743,6 +2116,24 @@ impl AstNode for ast::ExprDict { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprDict { + keys, + values, + range: _, + } = self; + + for (key, value) in keys.iter().zip(values) { + if let Some(key) = key { + visitor.visit_expr(key); + } + visitor.visit_expr(value); + } + } } impl AstNode for ast::ExprSet { fn cast(kind: AnyNode) -> Option @@ -1771,6 +2162,17 @@ impl AstNode for ast::ExprSet { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSet { elts, range: _ } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprListComp { fn cast(kind: AnyNode) -> Option @@ -1799,6 +2201,22 @@ impl AstNode for ast::ExprListComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprListComp { + elt, + generators, + range: _, + } = self; + + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprSetComp { fn cast(kind: AnyNode) -> Option @@ -1827,6 +2245,22 @@ impl AstNode for ast::ExprSetComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSetComp { + elt, + generators, + range: _, + } = self; + + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprDictComp { fn cast(kind: AnyNode) -> Option @@ -1855,6 +2289,25 @@ impl AstNode for ast::ExprDictComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprDictComp { + key, + value, + generators, + range: _, + } = self; + + visitor.visit_expr(key); + visitor.visit_expr(value); + + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprGeneratorExp { fn cast(kind: AnyNode) -> Option @@ -1883,6 +2336,21 @@ impl AstNode for ast::ExprGeneratorExp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprGeneratorExp { + elt, + generators, + range: _, + } = self; + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprAwait { fn cast(kind: AnyNode) -> Option @@ -1911,6 +2379,14 @@ impl AstNode for ast::ExprAwait { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprAwait { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::ExprYield { fn cast(kind: AnyNode) -> Option @@ -1939,6 +2415,16 @@ impl AstNode for ast::ExprYield { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprYield { value, range: _ } = self; + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprYieldFrom { fn cast(kind: AnyNode) -> Option @@ -1967,6 +2453,14 @@ impl AstNode for ast::ExprYieldFrom { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprYieldFrom { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::ExprCompare { fn cast(kind: AnyNode) -> Option @@ -1995,6 +2489,25 @@ impl AstNode for ast::ExprCompare { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprCompare { + left, + ops, + comparators, + range: _, + } = self; + + visitor.visit_expr(left); + + for (op, comparator) in ops.iter().zip(comparators) { + visitor.visit_cmp_op(op); + visitor.visit_expr(comparator); + } + } } impl AstNode for ast::ExprCall { fn cast(kind: AnyNode) -> Option @@ -2023,6 +2536,19 @@ impl AstNode for ast::ExprCall { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprCall { + func, + arguments, + range: _, + } = self; + visitor.visit_expr(func); + visitor.visit_arguments(arguments); + } } impl AstNode for ast::ExprFormattedValue { fn cast(kind: AnyNode) -> Option @@ -2051,13 +2577,27 @@ impl AstNode for ast::ExprFormattedValue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprFormattedValue { + value, format_spec, .. + } = self; + visitor.visit_expr(value); + + if let Some(expr) = format_spec { + visitor.visit_format_spec(expr); + } + } } -impl AstNode for ast::ExprJoinedStr { +impl AstNode for ast::ExprFString { fn cast(kind: AnyNode) -> Option where Self: Sized, { - if let AnyNode::ExprJoinedStr(node) = kind { + if let AnyNode::ExprFString(node) = kind { Some(node) } else { None @@ -2065,7 +2605,7 @@ impl AstNode for ast::ExprJoinedStr { } fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::ExprJoinedStr(node) = kind { + if let AnyNodeRef::ExprFString(node) = kind { Some(node) } else { None @@ -2079,6 +2619,21 @@ impl AstNode for ast::ExprJoinedStr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprFString { + values, + implicit_concatenated: _, + range: _, + } = self; + + for expr in values { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprConstant { fn cast(kind: AnyNode) -> Option @@ -2107,6 +2662,18 @@ impl AstNode for ast::ExprConstant { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprConstant { + value, + range: _, + kind: _, + } = self; + visitor.visit_constant(value); + } } impl AstNode for ast::ExprAttribute { fn cast(kind: AnyNode) -> Option @@ -2135,6 +2702,20 @@ impl AstNode for ast::ExprAttribute { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprAttribute { + value, + attr: _, + ctx: _, + range: _, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::ExprSubscript { fn cast(kind: AnyNode) -> Option @@ -2163,6 +2744,20 @@ impl AstNode for ast::ExprSubscript { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSubscript { + value, + slice, + ctx: _, + range: _, + } = self; + visitor.visit_expr(value); + visitor.visit_expr(slice); + } } impl AstNode for ast::ExprStarred { fn cast(kind: AnyNode) -> Option @@ -2191,6 +2786,19 @@ impl AstNode for ast::ExprStarred { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprStarred { + value, + ctx: _, + range: _, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::ExprName { fn cast(kind: AnyNode) -> Option @@ -2219,6 +2827,18 @@ impl AstNode for ast::ExprName { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprName { + id: _, + ctx: _, + range: _, + } = self; + } } impl AstNode for ast::ExprList { fn cast(kind: AnyNode) -> Option @@ -2247,6 +2867,21 @@ impl AstNode for ast::ExprList { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprList { + elts, + ctx: _, + range: _, + } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprTuple { fn cast(kind: AnyNode) -> Option @@ -2275,6 +2910,21 @@ impl AstNode for ast::ExprTuple { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprTuple { + elts, + ctx: _, + range: _, + } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprSlice { fn cast(kind: AnyNode) -> Option @@ -2303,13 +2953,34 @@ impl AstNode for ast::ExprSlice { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSlice { + lower, + upper, + step, + range: _, + } = self; + + if let Some(expr) = lower { + visitor.visit_expr(expr); + } + if let Some(expr) = upper { + visitor.visit_expr(expr); + } + if let Some(expr) = step { + visitor.visit_expr(expr); + } + } } -impl AstNode for ast::ExprLineMagic { +impl AstNode for ast::ExprIpyEscapeCommand { fn cast(kind: AnyNode) -> Option where Self: Sized, { - if let AnyNode::ExprLineMagic(node) = kind { + if let AnyNode::ExprIpyEscapeCommand(node) = kind { Some(node) } else { None @@ -2317,7 +2988,7 @@ impl AstNode for ast::ExprLineMagic { } fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::ExprLineMagic(node) = kind { + if let AnyNodeRef::ExprIpyEscapeCommand(node) = kind { Some(node) } else { None @@ -2331,6 +3002,18 @@ impl AstNode for ast::ExprLineMagic { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprIpyEscapeCommand { + range: _, + kind: _, + value: _, + } = self; + } } impl AstNode for ast::ExceptHandlerExceptHandler { fn cast(kind: AnyNode) -> Option @@ -2359,6 +3042,22 @@ impl AstNode for ast::ExceptHandlerExceptHandler { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExceptHandlerExceptHandler { + range: _, + type_, + name: _, + body, + } = self; + if let Some(expr) = type_ { + visitor.visit_expr(expr); + } + visitor.visit_body(body); + } } impl AstNode for ast::PatternMatchValue { fn cast(kind: AnyNode) -> Option @@ -2387,6 +3086,14 @@ impl AstNode for ast::PatternMatchValue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchValue { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::PatternMatchSingleton { fn cast(kind: AnyNode) -> Option @@ -2415,6 +3122,14 @@ impl AstNode for ast::PatternMatchSingleton { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchSingleton { value, range: _ } = self; + visitor.visit_constant(value); + } } impl AstNode for ast::PatternMatchSequence { fn cast(kind: AnyNode) -> Option @@ -2443,6 +3158,16 @@ impl AstNode for ast::PatternMatchSequence { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchSequence { patterns, range: _ } = self; + for pattern in patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchMapping { fn cast(kind: AnyNode) -> Option @@ -2471,6 +3196,22 @@ impl AstNode for ast::PatternMatchMapping { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchMapping { + keys, + patterns, + range: _, + rest: _, + } = self; + for (key, pattern) in keys.iter().zip(patterns) { + visitor.visit_expr(key); + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchClass { fn cast(kind: AnyNode) -> Option @@ -2499,6 +3240,27 @@ impl AstNode for ast::PatternMatchClass { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchClass { + cls, + patterns, + kwd_attrs: _, + kwd_patterns, + range: _, + } = self; + visitor.visit_expr(cls); + for pattern in patterns { + visitor.visit_pattern(pattern); + } + + for pattern in kwd_patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchStar { fn cast(kind: AnyNode) -> Option @@ -2527,6 +3289,14 @@ impl AstNode for ast::PatternMatchStar { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchStar { range: _, name: _ } = self; + } } impl AstNode for ast::PatternMatchAs { fn cast(kind: AnyNode) -> Option @@ -2555,6 +3325,20 @@ impl AstNode for ast::PatternMatchAs { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchAs { + pattern, + range: _, + name: _, + } = self; + if let Some(pattern) = pattern { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchOr { fn cast(kind: AnyNode) -> Option @@ -2583,6 +3367,16 @@ impl AstNode for ast::PatternMatchOr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchOr { patterns, range: _ } = self; + for pattern in patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for Comprehension { @@ -2612,6 +3406,25 @@ impl AstNode for Comprehension { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Comprehension { + range: _, + target, + iter, + ifs, + is_async: _, + } = self; + visitor.visit_expr(target); + visitor.visit_expr(iter); + + for expr in ifs { + visitor.visit_expr(expr); + } + } } impl AstNode for Arguments { fn cast(kind: AnyNode) -> Option @@ -2640,13 +3453,89 @@ impl AstNode for Arguments { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Arguments { + range: _, + args, + keywords, + } = self; + + for arg in args { + visitor.visit_expr(arg); + } + + for keyword in keywords { + visitor.visit_keyword(keyword); + } + } +} +impl AstNode for Parameters { + fn cast(kind: AnyNode) -> Option + where + Self: Sized, + { + if let AnyNode::Parameters(node) = kind { + Some(node) + } else { + None + } + } + + fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { + if let AnyNodeRef::Parameters(node) = kind { + Some(node) + } else { + None + } + } + + fn as_any_node_ref(&self) -> AnyNodeRef { + AnyNodeRef::from(self) + } + + fn into_any_node(self) -> AnyNode { + AnyNode::from(self) + } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Parameters { + range: _, + posonlyargs, + args, + vararg, + kwonlyargs, + kwarg, + } = self; + for arg in posonlyargs.iter().chain(args) { + visitor.visit_parameter_with_default(arg); + } + + if let Some(arg) = vararg { + visitor.visit_parameter(arg); + } + + for arg in kwonlyargs { + visitor.visit_parameter_with_default(arg); + } + + if let Some(arg) = kwarg { + visitor.visit_parameter(arg); + } + } } -impl AstNode for Arg { +impl AstNode for Parameter { fn cast(kind: AnyNode) -> Option where Self: Sized, { - if let AnyNode::Arg(node) = kind { + if let AnyNode::Parameter(node) = kind { Some(node) } else { None @@ -2654,7 +3543,7 @@ impl AstNode for Arg { } fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::Arg(node) = kind { + if let AnyNodeRef::Parameter(node) = kind { Some(node) } else { None @@ -2668,13 +3557,28 @@ impl AstNode for Arg { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Parameter { + range: _, + name: _, + annotation, + } = self; + + if let Some(expr) = annotation { + visitor.visit_annotation(expr); + } + } } -impl AstNode for ArgWithDefault { +impl AstNode for ParameterWithDefault { fn cast(kind: AnyNode) -> Option where Self: Sized, { - if let AnyNode::ArgWithDefault(node) = kind { + if let AnyNode::ParameterWithDefault(node) = kind { Some(node) } else { None @@ -2682,7 +3586,7 @@ impl AstNode for ArgWithDefault { } fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { - if let AnyNodeRef::ArgWithDefault(node) = kind { + if let AnyNodeRef::ParameterWithDefault(node) = kind { Some(node) } else { None @@ -2696,6 +3600,21 @@ impl AstNode for ArgWithDefault { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ParameterWithDefault { + range: _, + parameter, + default, + } = self; + visitor.visit_parameter(parameter); + if let Some(expr) = default { + visitor.visit_expr(expr); + } + } } impl AstNode for Keyword { fn cast(kind: AnyNode) -> Option @@ -2724,6 +3643,19 @@ impl AstNode for Keyword { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Keyword { + range: _, + arg: _, + value, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for Alias { fn cast(kind: AnyNode) -> Option @@ -2752,6 +3684,18 @@ impl AstNode for Alias { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Alias { + range: _, + name: _, + asname: _, + } = self; + } } impl AstNode for WithItem { fn cast(kind: AnyNode) -> Option @@ -2780,6 +3724,23 @@ impl AstNode for WithItem { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::WithItem { + range: _, + context_expr, + optional_vars, + } = self; + + visitor.visit_expr(context_expr); + + if let Some(expr) = optional_vars { + visitor.visit_expr(expr); + } + } } impl AstNode for MatchCase { fn cast(kind: AnyNode) -> Option @@ -2808,6 +3769,24 @@ impl AstNode for MatchCase { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::MatchCase { + range: _, + pattern, + guard, + body, + } = self; + + visitor.visit_pattern(pattern); + if let Some(expr) = guard { + visitor.visit_expr(expr); + } + visitor.visit_body(body); + } } impl AstNode for Decorator { @@ -2837,6 +3816,60 @@ impl AstNode for Decorator { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Decorator { + range: _, + expression, + } = self; + + visitor.visit_expr(expression); + } +} +impl AstNode for ast::TypeParams { + fn cast(kind: AnyNode) -> Option + where + Self: Sized, + { + if let AnyNode::TypeParams(node) = kind { + Some(node) + } else { + None + } + } + + fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { + if let AnyNodeRef::TypeParams(node) = kind { + Some(node) + } else { + None + } + } + + fn as_any_node_ref(&self) -> AnyNodeRef { + AnyNodeRef::from(self) + } + + fn into_any_node(self) -> AnyNode { + AnyNode::from(self) + } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParams { + range: _, + type_params, + } = self; + + for type_param in type_params { + visitor.visit_type_param(type_param); + } + } } impl AstNode for ast::TypeParamTypeVar { fn cast(kind: AnyNode) -> Option @@ -2865,6 +3898,21 @@ impl AstNode for ast::TypeParamTypeVar { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamTypeVar { + bound, + name: _, + range: _, + } = self; + + if let Some(expr) = bound { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::TypeParamTypeVarTuple { fn cast(kind: AnyNode) -> Option @@ -2893,6 +3941,14 @@ impl AstNode for ast::TypeParamTypeVarTuple { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamTypeVarTuple { range: _, name: _ } = self; + } } impl AstNode for ast::TypeParamParamSpec { fn cast(kind: AnyNode) -> Option @@ -2921,12 +3977,19 @@ impl AstNode for ast::TypeParamParamSpec { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamParamSpec { range: _, name: _ } = self; + } } impl From for AnyNode { fn from(stmt: Stmt) -> Self { match stmt { Stmt::FunctionDef(node) => AnyNode::StmtFunctionDef(node), - Stmt::AsyncFunctionDef(node) => AnyNode::StmtAsyncFunctionDef(node), Stmt::ClassDef(node) => AnyNode::StmtClassDef(node), Stmt::Return(node) => AnyNode::StmtReturn(node), Stmt::Delete(node) => AnyNode::StmtDelete(node), @@ -2935,15 +3998,12 @@ impl From for AnyNode { Stmt::AugAssign(node) => AnyNode::StmtAugAssign(node), Stmt::AnnAssign(node) => AnyNode::StmtAnnAssign(node), Stmt::For(node) => AnyNode::StmtFor(node), - Stmt::AsyncFor(node) => AnyNode::StmtAsyncFor(node), Stmt::While(node) => AnyNode::StmtWhile(node), Stmt::If(node) => AnyNode::StmtIf(node), Stmt::With(node) => AnyNode::StmtWith(node), - Stmt::AsyncWith(node) => AnyNode::StmtAsyncWith(node), Stmt::Match(node) => AnyNode::StmtMatch(node), Stmt::Raise(node) => AnyNode::StmtRaise(node), Stmt::Try(node) => AnyNode::StmtTry(node), - Stmt::TryStar(node) => AnyNode::StmtTryStar(node), Stmt::Assert(node) => AnyNode::StmtAssert(node), Stmt::Import(node) => AnyNode::StmtImport(node), Stmt::ImportFrom(node) => AnyNode::StmtImportFrom(node), @@ -2953,7 +4013,7 @@ impl From for AnyNode { Stmt::Pass(node) => AnyNode::StmtPass(node), Stmt::Break(node) => AnyNode::StmtBreak(node), Stmt::Continue(node) => AnyNode::StmtContinue(node), - Stmt::LineMagic(node) => AnyNode::StmtLineMagic(node), + Stmt::IpyEscapeCommand(node) => AnyNode::StmtIpyEscapeCommand(node), } } } @@ -2979,7 +4039,7 @@ impl From for AnyNode { Expr::Compare(node) => AnyNode::ExprCompare(node), Expr::Call(node) => AnyNode::ExprCall(node), Expr::FormattedValue(node) => AnyNode::ExprFormattedValue(node), - Expr::JoinedStr(node) => AnyNode::ExprJoinedStr(node), + Expr::FString(node) => AnyNode::ExprFString(node), Expr::Constant(node) => AnyNode::ExprConstant(node), Expr::Attribute(node) => AnyNode::ExprAttribute(node), Expr::Subscript(node) => AnyNode::ExprSubscript(node), @@ -2988,7 +4048,7 @@ impl From for AnyNode { Expr::List(node) => AnyNode::ExprList(node), Expr::Tuple(node) => AnyNode::ExprTuple(node), Expr::Slice(node) => AnyNode::ExprSlice(node), - Expr::LineMagic(node) => AnyNode::ExprLineMagic(node), + Expr::IpyEscapeCommand(node) => AnyNode::ExprIpyEscapeCommand(node), } } } @@ -3043,12 +4103,6 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::StmtAsyncFunctionDef) -> Self { - AnyNode::StmtAsyncFunctionDef(node) - } -} - impl From for AnyNode { fn from(node: ast::StmtClassDef) -> Self { AnyNode::StmtClassDef(node) @@ -3097,12 +4151,6 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::StmtAsyncFor) -> Self { - AnyNode::StmtAsyncFor(node) - } -} - impl From for AnyNode { fn from(node: ast::StmtWhile) -> Self { AnyNode::StmtWhile(node) @@ -3127,12 +4175,6 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::StmtAsyncWith) -> Self { - AnyNode::StmtAsyncWith(node) - } -} - impl From for AnyNode { fn from(node: ast::StmtMatch) -> Self { AnyNode::StmtMatch(node) @@ -3151,12 +4193,6 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::StmtTryStar) -> Self { - AnyNode::StmtTryStar(node) - } -} - impl From for AnyNode { fn from(node: ast::StmtAssert) -> Self { AnyNode::StmtAssert(node) @@ -3211,9 +4247,9 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::StmtLineMagic) -> Self { - AnyNode::StmtLineMagic(node) +impl From for AnyNode { + fn from(node: ast::StmtIpyEscapeCommand) -> Self { + AnyNode::StmtIpyEscapeCommand(node) } } @@ -3325,9 +4361,9 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::ExprJoinedStr) -> Self { - AnyNode::ExprJoinedStr(node) +impl From for AnyNode { + fn from(node: ast::ExprFString) -> Self { + AnyNode::ExprFString(node) } } @@ -3379,9 +4415,9 @@ impl From for AnyNode { } } -impl From for AnyNode { - fn from(node: ast::ExprLineMagic) -> Self { - AnyNode::ExprLineMagic(node) +impl From for AnyNode { + fn from(node: ast::ExprIpyEscapeCommand) -> Self { + AnyNode::ExprIpyEscapeCommand(node) } } @@ -3449,14 +4485,19 @@ impl From for AnyNode { AnyNode::Arguments(node) } } -impl From for AnyNode { - fn from(node: Arg) -> Self { - AnyNode::Arg(node) +impl From for AnyNode { + fn from(node: Parameters) -> Self { + AnyNode::Parameters(node) + } +} +impl From for AnyNode { + fn from(node: Parameter) -> Self { + AnyNode::Parameter(node) } } -impl From for AnyNode { - fn from(node: ArgWithDefault) -> Self { - AnyNode::ArgWithDefault(node) +impl From for AnyNode { + fn from(node: ParameterWithDefault) -> Self { + AnyNode::ParameterWithDefault(node) } } impl From for AnyNode { @@ -3484,6 +4525,11 @@ impl From for AnyNode { AnyNode::Decorator(node) } } +impl From for AnyNode { + fn from(node: TypeParams) -> Self { + AnyNode::TypeParams(node) + } +} impl From for AnyNode { fn from(node: TypeParamTypeVar) -> Self { AnyNode::TypeParamTypeVar(node) @@ -3508,7 +4554,6 @@ impl Ranged for AnyNode { AnyNode::ModModule(node) => node.range(), AnyNode::ModExpression(node) => node.range(), AnyNode::StmtFunctionDef(node) => node.range(), - AnyNode::StmtAsyncFunctionDef(node) => node.range(), AnyNode::StmtClassDef(node) => node.range(), AnyNode::StmtReturn(node) => node.range(), AnyNode::StmtDelete(node) => node.range(), @@ -3517,15 +4562,12 @@ impl Ranged for AnyNode { AnyNode::StmtAugAssign(node) => node.range(), AnyNode::StmtAnnAssign(node) => node.range(), AnyNode::StmtFor(node) => node.range(), - AnyNode::StmtAsyncFor(node) => node.range(), AnyNode::StmtWhile(node) => node.range(), AnyNode::StmtIf(node) => node.range(), AnyNode::StmtWith(node) => node.range(), - AnyNode::StmtAsyncWith(node) => node.range(), AnyNode::StmtMatch(node) => node.range(), AnyNode::StmtRaise(node) => node.range(), AnyNode::StmtTry(node) => node.range(), - AnyNode::StmtTryStar(node) => node.range(), AnyNode::StmtAssert(node) => node.range(), AnyNode::StmtImport(node) => node.range(), AnyNode::StmtImportFrom(node) => node.range(), @@ -3535,7 +4577,7 @@ impl Ranged for AnyNode { AnyNode::StmtPass(node) => node.range(), AnyNode::StmtBreak(node) => node.range(), AnyNode::StmtContinue(node) => node.range(), - AnyNode::StmtLineMagic(node) => node.range(), + AnyNode::StmtIpyEscapeCommand(node) => node.range(), AnyNode::ExprBoolOp(node) => node.range(), AnyNode::ExprNamedExpr(node) => node.range(), AnyNode::ExprBinOp(node) => node.range(), @@ -3554,7 +4596,7 @@ impl Ranged for AnyNode { AnyNode::ExprCompare(node) => node.range(), AnyNode::ExprCall(node) => node.range(), AnyNode::ExprFormattedValue(node) => node.range(), - AnyNode::ExprJoinedStr(node) => node.range(), + AnyNode::ExprFString(node) => node.range(), AnyNode::ExprConstant(node) => node.range(), AnyNode::ExprAttribute(node) => node.range(), AnyNode::ExprSubscript(node) => node.range(), @@ -3563,7 +4605,7 @@ impl Ranged for AnyNode { AnyNode::ExprList(node) => node.range(), AnyNode::ExprTuple(node) => node.range(), AnyNode::ExprSlice(node) => node.range(), - AnyNode::ExprLineMagic(node) => node.range(), + AnyNode::ExprIpyEscapeCommand(node) => node.range(), AnyNode::ExceptHandlerExceptHandler(node) => node.range(), AnyNode::PatternMatchValue(node) => node.range(), AnyNode::PatternMatchSingleton(node) => node.range(), @@ -3575,13 +4617,15 @@ impl Ranged for AnyNode { AnyNode::PatternMatchOr(node) => node.range(), AnyNode::Comprehension(node) => node.range(), AnyNode::Arguments(node) => node.range(), - AnyNode::Arg(node) => node.range(), - AnyNode::ArgWithDefault(node) => node.range(), + AnyNode::Parameters(node) => node.range(), + AnyNode::Parameter(node) => node.range(), + AnyNode::ParameterWithDefault(node) => node.range(), AnyNode::Keyword(node) => node.range(), AnyNode::Alias(node) => node.range(), AnyNode::WithItem(node) => node.range(), AnyNode::MatchCase(node) => node.range(), AnyNode::Decorator(node) => node.range(), + AnyNode::TypeParams(node) => node.range(), AnyNode::TypeParamTypeVar(node) => node.range(), AnyNode::TypeParamTypeVarTuple(node) => node.range(), AnyNode::TypeParamParamSpec(node) => node.range(), @@ -3595,7 +4639,6 @@ pub enum AnyNodeRef<'a> { ModModule(&'a ast::ModModule), ModExpression(&'a ast::ModExpression), StmtFunctionDef(&'a ast::StmtFunctionDef), - StmtAsyncFunctionDef(&'a ast::StmtAsyncFunctionDef), StmtClassDef(&'a ast::StmtClassDef), StmtReturn(&'a ast::StmtReturn), StmtDelete(&'a ast::StmtDelete), @@ -3604,15 +4647,12 @@ pub enum AnyNodeRef<'a> { StmtAugAssign(&'a ast::StmtAugAssign), StmtAnnAssign(&'a ast::StmtAnnAssign), StmtFor(&'a ast::StmtFor), - StmtAsyncFor(&'a ast::StmtAsyncFor), StmtWhile(&'a ast::StmtWhile), StmtIf(&'a ast::StmtIf), StmtWith(&'a ast::StmtWith), - StmtAsyncWith(&'a ast::StmtAsyncWith), StmtMatch(&'a ast::StmtMatch), StmtRaise(&'a ast::StmtRaise), StmtTry(&'a ast::StmtTry), - StmtTryStar(&'a ast::StmtTryStar), StmtAssert(&'a ast::StmtAssert), StmtImport(&'a ast::StmtImport), StmtImportFrom(&'a ast::StmtImportFrom), @@ -3622,7 +4662,7 @@ pub enum AnyNodeRef<'a> { StmtPass(&'a ast::StmtPass), StmtBreak(&'a ast::StmtBreak), StmtContinue(&'a ast::StmtContinue), - StmtLineMagic(&'a ast::StmtLineMagic), + StmtIpyEscapeCommand(&'a ast::StmtIpyEscapeCommand), ExprBoolOp(&'a ast::ExprBoolOp), ExprNamedExpr(&'a ast::ExprNamedExpr), ExprBinOp(&'a ast::ExprBinOp), @@ -3641,7 +4681,7 @@ pub enum AnyNodeRef<'a> { ExprCompare(&'a ast::ExprCompare), ExprCall(&'a ast::ExprCall), ExprFormattedValue(&'a ast::ExprFormattedValue), - ExprJoinedStr(&'a ast::ExprJoinedStr), + ExprFString(&'a ast::ExprFString), ExprConstant(&'a ast::ExprConstant), ExprAttribute(&'a ast::ExprAttribute), ExprSubscript(&'a ast::ExprSubscript), @@ -3650,7 +4690,7 @@ pub enum AnyNodeRef<'a> { ExprList(&'a ast::ExprList), ExprTuple(&'a ast::ExprTuple), ExprSlice(&'a ast::ExprSlice), - ExprLineMagic(&'a ast::ExprLineMagic), + ExprIpyEscapeCommand(&'a ast::ExprIpyEscapeCommand), ExceptHandlerExceptHandler(&'a ast::ExceptHandlerExceptHandler), PatternMatchValue(&'a ast::PatternMatchValue), PatternMatchSingleton(&'a ast::PatternMatchSingleton), @@ -3662,16 +4702,18 @@ pub enum AnyNodeRef<'a> { PatternMatchOr(&'a ast::PatternMatchOr), Comprehension(&'a Comprehension), Arguments(&'a Arguments), - Arg(&'a Arg), - ArgWithDefault(&'a ArgWithDefault), + Parameters(&'a Parameters), + Parameter(&'a Parameter), + ParameterWithDefault(&'a ParameterWithDefault), Keyword(&'a Keyword), Alias(&'a Alias), WithItem(&'a WithItem), MatchCase(&'a MatchCase), Decorator(&'a Decorator), - TypeParamTypeVar(&'a ast::TypeParamTypeVar), - TypeParamTypeVarTuple(&'a ast::TypeParamTypeVarTuple), - TypeParamParamSpec(&'a ast::TypeParamParamSpec), + TypeParams(&'a TypeParams), + TypeParamTypeVar(&'a TypeParamTypeVar), + TypeParamTypeVarTuple(&'a TypeParamTypeVarTuple), + TypeParamParamSpec(&'a TypeParamParamSpec), ElifElseClause(&'a ast::ElifElseClause), } @@ -3681,7 +4723,6 @@ impl AnyNodeRef<'_> { AnyNodeRef::ModModule(node) => NonNull::from(*node).cast(), AnyNodeRef::ModExpression(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtFunctionDef(node) => NonNull::from(*node).cast(), - AnyNodeRef::StmtAsyncFunctionDef(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtClassDef(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtReturn(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtDelete(node) => NonNull::from(*node).cast(), @@ -3690,15 +4731,12 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtAugAssign(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtAnnAssign(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtFor(node) => NonNull::from(*node).cast(), - AnyNodeRef::StmtAsyncFor(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtWhile(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtIf(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtWith(node) => NonNull::from(*node).cast(), - AnyNodeRef::StmtAsyncWith(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtMatch(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtRaise(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtTry(node) => NonNull::from(*node).cast(), - AnyNodeRef::StmtTryStar(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtAssert(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtImport(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtImportFrom(node) => NonNull::from(*node).cast(), @@ -3708,7 +4746,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtPass(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtBreak(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtContinue(node) => NonNull::from(*node).cast(), - AnyNodeRef::StmtLineMagic(node) => NonNull::from(*node).cast(), + AnyNodeRef::StmtIpyEscapeCommand(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprBoolOp(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprNamedExpr(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprBinOp(node) => NonNull::from(*node).cast(), @@ -3727,7 +4765,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprCompare(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprCall(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprFormattedValue(node) => NonNull::from(*node).cast(), - AnyNodeRef::ExprJoinedStr(node) => NonNull::from(*node).cast(), + AnyNodeRef::ExprFString(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprConstant(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprAttribute(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprSubscript(node) => NonNull::from(*node).cast(), @@ -3736,7 +4774,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprList(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprTuple(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprSlice(node) => NonNull::from(*node).cast(), - AnyNodeRef::ExprLineMagic(node) => NonNull::from(*node).cast(), + AnyNodeRef::ExprIpyEscapeCommand(node) => NonNull::from(*node).cast(), AnyNodeRef::ExceptHandlerExceptHandler(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchValue(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSingleton(node) => NonNull::from(*node).cast(), @@ -3748,13 +4786,15 @@ impl AnyNodeRef<'_> { AnyNodeRef::PatternMatchOr(node) => NonNull::from(*node).cast(), AnyNodeRef::Comprehension(node) => NonNull::from(*node).cast(), AnyNodeRef::Arguments(node) => NonNull::from(*node).cast(), - AnyNodeRef::Arg(node) => NonNull::from(*node).cast(), - AnyNodeRef::ArgWithDefault(node) => NonNull::from(*node).cast(), + AnyNodeRef::Parameters(node) => NonNull::from(*node).cast(), + AnyNodeRef::Parameter(node) => NonNull::from(*node).cast(), + AnyNodeRef::ParameterWithDefault(node) => NonNull::from(*node).cast(), AnyNodeRef::Keyword(node) => NonNull::from(*node).cast(), AnyNodeRef::Alias(node) => NonNull::from(*node).cast(), AnyNodeRef::WithItem(node) => NonNull::from(*node).cast(), AnyNodeRef::MatchCase(node) => NonNull::from(*node).cast(), AnyNodeRef::Decorator(node) => NonNull::from(*node).cast(), + AnyNodeRef::TypeParams(node) => NonNull::from(*node).cast(), AnyNodeRef::TypeParamTypeVar(node) => NonNull::from(*node).cast(), AnyNodeRef::TypeParamTypeVarTuple(node) => NonNull::from(*node).cast(), AnyNodeRef::TypeParamParamSpec(node) => NonNull::from(*node).cast(), @@ -3773,7 +4813,6 @@ impl AnyNodeRef<'_> { AnyNodeRef::ModModule(_) => NodeKind::ModModule, AnyNodeRef::ModExpression(_) => NodeKind::ModExpression, AnyNodeRef::StmtFunctionDef(_) => NodeKind::StmtFunctionDef, - AnyNodeRef::StmtAsyncFunctionDef(_) => NodeKind::StmtAsyncFunctionDef, AnyNodeRef::StmtClassDef(_) => NodeKind::StmtClassDef, AnyNodeRef::StmtReturn(_) => NodeKind::StmtReturn, AnyNodeRef::StmtDelete(_) => NodeKind::StmtDelete, @@ -3782,15 +4821,12 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtAugAssign(_) => NodeKind::StmtAugAssign, AnyNodeRef::StmtAnnAssign(_) => NodeKind::StmtAnnAssign, AnyNodeRef::StmtFor(_) => NodeKind::StmtFor, - AnyNodeRef::StmtAsyncFor(_) => NodeKind::StmtAsyncFor, AnyNodeRef::StmtWhile(_) => NodeKind::StmtWhile, AnyNodeRef::StmtIf(_) => NodeKind::StmtIf, AnyNodeRef::StmtWith(_) => NodeKind::StmtWith, - AnyNodeRef::StmtAsyncWith(_) => NodeKind::StmtAsyncWith, AnyNodeRef::StmtMatch(_) => NodeKind::StmtMatch, AnyNodeRef::StmtRaise(_) => NodeKind::StmtRaise, AnyNodeRef::StmtTry(_) => NodeKind::StmtTry, - AnyNodeRef::StmtTryStar(_) => NodeKind::StmtTryStar, AnyNodeRef::StmtAssert(_) => NodeKind::StmtAssert, AnyNodeRef::StmtImport(_) => NodeKind::StmtImport, AnyNodeRef::StmtImportFrom(_) => NodeKind::StmtImportFrom, @@ -3800,7 +4836,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtPass(_) => NodeKind::StmtPass, AnyNodeRef::StmtBreak(_) => NodeKind::StmtBreak, AnyNodeRef::StmtContinue(_) => NodeKind::StmtContinue, - AnyNodeRef::StmtLineMagic(_) => NodeKind::StmtLineMagic, + AnyNodeRef::StmtIpyEscapeCommand(_) => NodeKind::StmtIpyEscapeCommand, AnyNodeRef::ExprBoolOp(_) => NodeKind::ExprBoolOp, AnyNodeRef::ExprNamedExpr(_) => NodeKind::ExprNamedExpr, AnyNodeRef::ExprBinOp(_) => NodeKind::ExprBinOp, @@ -3819,7 +4855,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprCompare(_) => NodeKind::ExprCompare, AnyNodeRef::ExprCall(_) => NodeKind::ExprCall, AnyNodeRef::ExprFormattedValue(_) => NodeKind::ExprFormattedValue, - AnyNodeRef::ExprJoinedStr(_) => NodeKind::ExprJoinedStr, + AnyNodeRef::ExprFString(_) => NodeKind::ExprFString, AnyNodeRef::ExprConstant(_) => NodeKind::ExprConstant, AnyNodeRef::ExprAttribute(_) => NodeKind::ExprAttribute, AnyNodeRef::ExprSubscript(_) => NodeKind::ExprSubscript, @@ -3828,7 +4864,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprList(_) => NodeKind::ExprList, AnyNodeRef::ExprTuple(_) => NodeKind::ExprTuple, AnyNodeRef::ExprSlice(_) => NodeKind::ExprSlice, - AnyNodeRef::ExprLineMagic(_) => NodeKind::ExprLineMagic, + AnyNodeRef::ExprIpyEscapeCommand(_) => NodeKind::ExprIpyEscapeCommand, AnyNodeRef::ExceptHandlerExceptHandler(_) => NodeKind::ExceptHandlerExceptHandler, AnyNodeRef::PatternMatchValue(_) => NodeKind::PatternMatchValue, AnyNodeRef::PatternMatchSingleton(_) => NodeKind::PatternMatchSingleton, @@ -3840,13 +4876,15 @@ impl AnyNodeRef<'_> { AnyNodeRef::PatternMatchOr(_) => NodeKind::PatternMatchOr, AnyNodeRef::Comprehension(_) => NodeKind::Comprehension, AnyNodeRef::Arguments(_) => NodeKind::Arguments, - AnyNodeRef::Arg(_) => NodeKind::Arg, - AnyNodeRef::ArgWithDefault(_) => NodeKind::ArgWithDefault, + AnyNodeRef::Parameters(_) => NodeKind::Parameters, + AnyNodeRef::Parameter(_) => NodeKind::Parameter, + AnyNodeRef::ParameterWithDefault(_) => NodeKind::ParameterWithDefault, AnyNodeRef::Keyword(_) => NodeKind::Keyword, AnyNodeRef::Alias(_) => NodeKind::Alias, AnyNodeRef::WithItem(_) => NodeKind::WithItem, AnyNodeRef::MatchCase(_) => NodeKind::MatchCase, AnyNodeRef::Decorator(_) => NodeKind::Decorator, + AnyNodeRef::TypeParams(_) => NodeKind::TypeParams, AnyNodeRef::TypeParamTypeVar(_) => NodeKind::TypeParamTypeVar, AnyNodeRef::TypeParamTypeVarTuple(_) => NodeKind::TypeParamTypeVarTuple, AnyNodeRef::TypeParamParamSpec(_) => NodeKind::TypeParamParamSpec, @@ -3857,7 +4895,6 @@ impl AnyNodeRef<'_> { pub const fn is_statement(self) -> bool { match self { AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) @@ -3866,15 +4903,12 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) @@ -3884,7 +4918,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) - | AnyNodeRef::StmtLineMagic(_) => true, + | AnyNodeRef::StmtIpyEscapeCommand(_) => true, AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) @@ -3906,7 +4940,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFormattedValue(_) - | AnyNodeRef::ExprJoinedStr(_) + | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprConstant(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) @@ -3915,7 +4949,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) - | AnyNodeRef::ExprLineMagic(_) + | AnyNodeRef::ExprIpyEscapeCommand(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -3927,13 +4961,15 @@ impl AnyNodeRef<'_> { | AnyNodeRef::PatternMatchOr(_) | AnyNodeRef::Comprehension(_) | AnyNodeRef::Arguments(_) - | AnyNodeRef::Arg(_) - | AnyNodeRef::ArgWithDefault(_) + | AnyNodeRef::Parameters(_) + | AnyNodeRef::Parameter(_) + | AnyNodeRef::ParameterWithDefault(_) | AnyNodeRef::Keyword(_) | AnyNodeRef::Alias(_) | AnyNodeRef::WithItem(_) | AnyNodeRef::MatchCase(_) | AnyNodeRef::Decorator(_) + | AnyNodeRef::TypeParams(_) | AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) @@ -3961,7 +4997,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFormattedValue(_) - | AnyNodeRef::ExprJoinedStr(_) + | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprConstant(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) @@ -3970,12 +5006,11 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) - | AnyNodeRef::ExprLineMagic(_) => true, + | AnyNodeRef::ExprIpyEscapeCommand(_) => true, AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) | AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) @@ -3984,15 +5019,12 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) @@ -4002,7 +5034,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) - | AnyNodeRef::StmtLineMagic(_) + | AnyNodeRef::StmtIpyEscapeCommand(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -4014,13 +5046,15 @@ impl AnyNodeRef<'_> { | AnyNodeRef::PatternMatchOr(_) | AnyNodeRef::Comprehension(_) | AnyNodeRef::Arguments(_) - | AnyNodeRef::Arg(_) - | AnyNodeRef::ArgWithDefault(_) + | AnyNodeRef::Parameters(_) + | AnyNodeRef::Parameter(_) + | AnyNodeRef::ParameterWithDefault(_) | AnyNodeRef::Keyword(_) | AnyNodeRef::Alias(_) | AnyNodeRef::WithItem(_) | AnyNodeRef::MatchCase(_) | AnyNodeRef::Decorator(_) + | AnyNodeRef::TypeParams(_) | AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) @@ -4033,7 +5067,6 @@ impl AnyNodeRef<'_> { AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) => true, AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) @@ -4042,15 +5075,12 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) @@ -4060,7 +5090,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) - | AnyNodeRef::StmtLineMagic(_) + | AnyNodeRef::StmtIpyEscapeCommand(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4079,7 +5109,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFormattedValue(_) - | AnyNodeRef::ExprJoinedStr(_) + | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprConstant(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) @@ -4088,7 +5118,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) - | AnyNodeRef::ExprLineMagic(_) + | AnyNodeRef::ExprIpyEscapeCommand(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -4100,13 +5130,15 @@ impl AnyNodeRef<'_> { | AnyNodeRef::PatternMatchOr(_) | AnyNodeRef::Comprehension(_) | AnyNodeRef::Arguments(_) - | AnyNodeRef::Arg(_) - | AnyNodeRef::ArgWithDefault(_) + | AnyNodeRef::Parameters(_) + | AnyNodeRef::Parameter(_) + | AnyNodeRef::ParameterWithDefault(_) | AnyNodeRef::Keyword(_) | AnyNodeRef::Alias(_) | AnyNodeRef::WithItem(_) | AnyNodeRef::MatchCase(_) | AnyNodeRef::Decorator(_) + | AnyNodeRef::TypeParams(_) | AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) @@ -4128,7 +5160,6 @@ impl AnyNodeRef<'_> { AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) | AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) @@ -4137,15 +5168,12 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) @@ -4155,7 +5183,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) - | AnyNodeRef::StmtLineMagic(_) + | AnyNodeRef::StmtIpyEscapeCommand(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4174,7 +5202,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFormattedValue(_) - | AnyNodeRef::ExprJoinedStr(_) + | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprConstant(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) @@ -4183,17 +5211,19 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) - | AnyNodeRef::ExprLineMagic(_) + | AnyNodeRef::ExprIpyEscapeCommand(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::Comprehension(_) | AnyNodeRef::Arguments(_) - | AnyNodeRef::Arg(_) - | AnyNodeRef::ArgWithDefault(_) + | AnyNodeRef::Parameters(_) + | AnyNodeRef::Parameter(_) + | AnyNodeRef::ParameterWithDefault(_) | AnyNodeRef::Keyword(_) | AnyNodeRef::Alias(_) | AnyNodeRef::WithItem(_) | AnyNodeRef::MatchCase(_) | AnyNodeRef::Decorator(_) + | AnyNodeRef::TypeParams(_) | AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) @@ -4208,7 +5238,6 @@ impl AnyNodeRef<'_> { AnyNodeRef::ModModule(_) | AnyNodeRef::ModExpression(_) | AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtReturn(_) | AnyNodeRef::StmtDelete(_) @@ -4217,15 +5246,12 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtAugAssign(_) | AnyNodeRef::StmtAnnAssign(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtRaise(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::StmtAssert(_) | AnyNodeRef::StmtImport(_) | AnyNodeRef::StmtImportFrom(_) @@ -4235,7 +5261,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) - | AnyNodeRef::StmtLineMagic(_) + | AnyNodeRef::StmtIpyEscapeCommand(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4254,7 +5280,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprCompare(_) | AnyNodeRef::ExprCall(_) | AnyNodeRef::ExprFormattedValue(_) - | AnyNodeRef::ExprJoinedStr(_) + | AnyNodeRef::ExprFString(_) | AnyNodeRef::ExprConstant(_) | AnyNodeRef::ExprAttribute(_) | AnyNodeRef::ExprSubscript(_) @@ -4263,7 +5289,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) - | AnyNodeRef::ExprLineMagic(_) + | AnyNodeRef::ExprIpyEscapeCommand(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSequence(_) @@ -4274,13 +5300,15 @@ impl AnyNodeRef<'_> { | AnyNodeRef::PatternMatchOr(_) | AnyNodeRef::Comprehension(_) | AnyNodeRef::Arguments(_) - | AnyNodeRef::Arg(_) - | AnyNodeRef::ArgWithDefault(_) + | AnyNodeRef::Parameters(_) + | AnyNodeRef::Parameter(_) + | AnyNodeRef::ParameterWithDefault(_) | AnyNodeRef::Keyword(_) | AnyNodeRef::Alias(_) | AnyNodeRef::WithItem(_) | AnyNodeRef::MatchCase(_) | AnyNodeRef::Decorator(_) + | AnyNodeRef::TypeParams(_) | AnyNodeRef::TypeParamTypeVar(_) | AnyNodeRef::TypeParamTypeVarTuple(_) | AnyNodeRef::TypeParamParamSpec(_) @@ -4293,16 +5321,12 @@ impl AnyNodeRef<'_> { self, AnyNodeRef::StmtIf(_) | AnyNodeRef::StmtFor(_) - | AnyNodeRef::StmtAsyncFor(_) | AnyNodeRef::StmtWhile(_) | AnyNodeRef::StmtWith(_) - | AnyNodeRef::StmtAsyncWith(_) | AnyNodeRef::StmtMatch(_) | AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtAsyncFunctionDef(_) | AnyNodeRef::StmtClassDef(_) | AnyNodeRef::StmtTry(_) - | AnyNodeRef::StmtTryStar(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::ElifElseClause(_) ) @@ -4317,6 +5341,93 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::ElifElseClause(_) ) } + + pub fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + match self { + AnyNodeRef::ModModule(node) => node.visit_preorder(visitor), + AnyNodeRef::ModExpression(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtFunctionDef(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtClassDef(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtReturn(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtDelete(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtTypeAlias(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAugAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAnnAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtFor(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtWhile(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtIf(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtWith(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtMatch(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtRaise(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtTry(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAssert(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtImport(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtImportFrom(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtGlobal(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtNonlocal(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtExpr(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtPass(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtBreak(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtContinue(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtIpyEscapeCommand(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprBoolOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprNamedExpr(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprBinOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprUnaryOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprLambda(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprIfExp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprDict(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSet(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprListComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSetComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprDictComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprGeneratorExp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprAwait(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprYield(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprYieldFrom(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprCompare(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprCall(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprFormattedValue(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprFString(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprConstant(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprAttribute(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSubscript(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprStarred(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprName(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprList(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprTuple(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSlice(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprIpyEscapeCommand(node) => node.visit_preorder(visitor), + AnyNodeRef::ExceptHandlerExceptHandler(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchValue(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchSingleton(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchSequence(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchMapping(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchClass(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchStar(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchAs(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchOr(node) => node.visit_preorder(visitor), + AnyNodeRef::Comprehension(node) => node.visit_preorder(visitor), + AnyNodeRef::Arguments(node) => node.visit_preorder(visitor), + AnyNodeRef::Parameters(node) => node.visit_preorder(visitor), + AnyNodeRef::Parameter(node) => node.visit_preorder(visitor), + AnyNodeRef::ParameterWithDefault(node) => node.visit_preorder(visitor), + AnyNodeRef::Keyword(node) => node.visit_preorder(visitor), + AnyNodeRef::Alias(node) => node.visit_preorder(visitor), + AnyNodeRef::WithItem(node) => node.visit_preorder(visitor), + AnyNodeRef::MatchCase(node) => node.visit_preorder(visitor), + AnyNodeRef::Decorator(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParams(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamTypeVar(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamTypeVarTuple(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamParamSpec(node) => node.visit_preorder(visitor), + AnyNodeRef::ElifElseClause(node) => node.visit_preorder(visitor), + } + } } impl<'a> From<&'a ast::ModModule> for AnyNodeRef<'a> { @@ -4337,12 +5448,6 @@ impl<'a> From<&'a ast::StmtFunctionDef> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::StmtAsyncFunctionDef> for AnyNodeRef<'a> { - fn from(node: &'a ast::StmtAsyncFunctionDef) -> Self { - AnyNodeRef::StmtAsyncFunctionDef(node) - } -} - impl<'a> From<&'a ast::StmtClassDef> for AnyNodeRef<'a> { fn from(node: &'a ast::StmtClassDef) -> Self { AnyNodeRef::StmtClassDef(node) @@ -4391,12 +5496,6 @@ impl<'a> From<&'a ast::StmtFor> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::StmtAsyncFor> for AnyNodeRef<'a> { - fn from(node: &'a ast::StmtAsyncFor) -> Self { - AnyNodeRef::StmtAsyncFor(node) - } -} - impl<'a> From<&'a ast::StmtWhile> for AnyNodeRef<'a> { fn from(node: &'a ast::StmtWhile) -> Self { AnyNodeRef::StmtWhile(node) @@ -4421,12 +5520,6 @@ impl<'a> From<&'a ast::StmtWith> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::StmtAsyncWith> for AnyNodeRef<'a> { - fn from(node: &'a ast::StmtAsyncWith) -> Self { - AnyNodeRef::StmtAsyncWith(node) - } -} - impl<'a> From<&'a ast::StmtMatch> for AnyNodeRef<'a> { fn from(node: &'a ast::StmtMatch) -> Self { AnyNodeRef::StmtMatch(node) @@ -4445,12 +5538,6 @@ impl<'a> From<&'a ast::StmtTry> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::StmtTryStar> for AnyNodeRef<'a> { - fn from(node: &'a ast::StmtTryStar) -> Self { - AnyNodeRef::StmtTryStar(node) - } -} - impl<'a> From<&'a ast::StmtAssert> for AnyNodeRef<'a> { fn from(node: &'a ast::StmtAssert) -> Self { AnyNodeRef::StmtAssert(node) @@ -4505,9 +5592,9 @@ impl<'a> From<&'a ast::StmtContinue> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::StmtLineMagic> for AnyNodeRef<'a> { - fn from(node: &'a ast::StmtLineMagic) -> Self { - AnyNodeRef::StmtLineMagic(node) +impl<'a> From<&'a ast::StmtIpyEscapeCommand> for AnyNodeRef<'a> { + fn from(node: &'a ast::StmtIpyEscapeCommand) -> Self { + AnyNodeRef::StmtIpyEscapeCommand(node) } } @@ -4619,9 +5706,9 @@ impl<'a> From<&'a ast::ExprFormattedValue> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::ExprJoinedStr> for AnyNodeRef<'a> { - fn from(node: &'a ast::ExprJoinedStr) -> Self { - AnyNodeRef::ExprJoinedStr(node) +impl<'a> From<&'a ast::ExprFString> for AnyNodeRef<'a> { + fn from(node: &'a ast::ExprFString) -> Self { + AnyNodeRef::ExprFString(node) } } @@ -4673,9 +5760,9 @@ impl<'a> From<&'a ast::ExprSlice> for AnyNodeRef<'a> { } } -impl<'a> From<&'a ast::ExprLineMagic> for AnyNodeRef<'a> { - fn from(node: &'a ast::ExprLineMagic) -> Self { - AnyNodeRef::ExprLineMagic(node) +impl<'a> From<&'a ast::ExprIpyEscapeCommand> for AnyNodeRef<'a> { + fn from(node: &'a ast::ExprIpyEscapeCommand) -> Self { + AnyNodeRef::ExprIpyEscapeCommand(node) } } @@ -4739,6 +5826,11 @@ impl<'a> From<&'a Decorator> for AnyNodeRef<'a> { } } +impl<'a> From<&'a ast::TypeParams> for AnyNodeRef<'a> { + fn from(node: &'a ast::TypeParams) -> Self { + AnyNodeRef::TypeParams(node) + } +} impl<'a> From<&'a TypeParamTypeVar> for AnyNodeRef<'a> { fn from(node: &'a TypeParamTypeVar) -> Self { AnyNodeRef::TypeParamTypeVar(node) @@ -4761,7 +5853,6 @@ impl<'a> From<&'a Stmt> for AnyNodeRef<'a> { fn from(stmt: &'a Stmt) -> Self { match stmt { Stmt::FunctionDef(node) => AnyNodeRef::StmtFunctionDef(node), - Stmt::AsyncFunctionDef(node) => AnyNodeRef::StmtAsyncFunctionDef(node), Stmt::ClassDef(node) => AnyNodeRef::StmtClassDef(node), Stmt::Return(node) => AnyNodeRef::StmtReturn(node), Stmt::Delete(node) => AnyNodeRef::StmtDelete(node), @@ -4770,15 +5861,12 @@ impl<'a> From<&'a Stmt> for AnyNodeRef<'a> { Stmt::AugAssign(node) => AnyNodeRef::StmtAugAssign(node), Stmt::AnnAssign(node) => AnyNodeRef::StmtAnnAssign(node), Stmt::For(node) => AnyNodeRef::StmtFor(node), - Stmt::AsyncFor(node) => AnyNodeRef::StmtAsyncFor(node), Stmt::While(node) => AnyNodeRef::StmtWhile(node), Stmt::If(node) => AnyNodeRef::StmtIf(node), Stmt::With(node) => AnyNodeRef::StmtWith(node), - Stmt::AsyncWith(node) => AnyNodeRef::StmtAsyncWith(node), Stmt::Match(node) => AnyNodeRef::StmtMatch(node), Stmt::Raise(node) => AnyNodeRef::StmtRaise(node), Stmt::Try(node) => AnyNodeRef::StmtTry(node), - Stmt::TryStar(node) => AnyNodeRef::StmtTryStar(node), Stmt::Assert(node) => AnyNodeRef::StmtAssert(node), Stmt::Import(node) => AnyNodeRef::StmtImport(node), Stmt::ImportFrom(node) => AnyNodeRef::StmtImportFrom(node), @@ -4788,7 +5876,7 @@ impl<'a> From<&'a Stmt> for AnyNodeRef<'a> { Stmt::Pass(node) => AnyNodeRef::StmtPass(node), Stmt::Break(node) => AnyNodeRef::StmtBreak(node), Stmt::Continue(node) => AnyNodeRef::StmtContinue(node), - Stmt::LineMagic(node) => AnyNodeRef::StmtLineMagic(node), + Stmt::IpyEscapeCommand(node) => AnyNodeRef::StmtIpyEscapeCommand(node), } } } @@ -4814,7 +5902,7 @@ impl<'a> From<&'a Expr> for AnyNodeRef<'a> { Expr::Compare(node) => AnyNodeRef::ExprCompare(node), Expr::Call(node) => AnyNodeRef::ExprCall(node), Expr::FormattedValue(node) => AnyNodeRef::ExprFormattedValue(node), - Expr::JoinedStr(node) => AnyNodeRef::ExprJoinedStr(node), + Expr::FString(node) => AnyNodeRef::ExprFString(node), Expr::Constant(node) => AnyNodeRef::ExprConstant(node), Expr::Attribute(node) => AnyNodeRef::ExprAttribute(node), Expr::Subscript(node) => AnyNodeRef::ExprSubscript(node), @@ -4823,7 +5911,7 @@ impl<'a> From<&'a Expr> for AnyNodeRef<'a> { Expr::List(node) => AnyNodeRef::ExprList(node), Expr::Tuple(node) => AnyNodeRef::ExprTuple(node), Expr::Slice(node) => AnyNodeRef::ExprSlice(node), - Expr::LineMagic(node) => AnyNodeRef::ExprLineMagic(node), + Expr::IpyEscapeCommand(node) => AnyNodeRef::ExprIpyEscapeCommand(node), } } } @@ -4882,14 +5970,19 @@ impl<'a> From<&'a Arguments> for AnyNodeRef<'a> { AnyNodeRef::Arguments(node) } } -impl<'a> From<&'a Arg> for AnyNodeRef<'a> { - fn from(node: &'a Arg) -> Self { - AnyNodeRef::Arg(node) +impl<'a> From<&'a Parameters> for AnyNodeRef<'a> { + fn from(node: &'a Parameters) -> Self { + AnyNodeRef::Parameters(node) + } +} +impl<'a> From<&'a Parameter> for AnyNodeRef<'a> { + fn from(node: &'a Parameter) -> Self { + AnyNodeRef::Parameter(node) } } -impl<'a> From<&'a ArgWithDefault> for AnyNodeRef<'a> { - fn from(node: &'a ArgWithDefault) -> Self { - AnyNodeRef::ArgWithDefault(node) +impl<'a> From<&'a ParameterWithDefault> for AnyNodeRef<'a> { + fn from(node: &'a ParameterWithDefault) -> Self { + AnyNodeRef::ParameterWithDefault(node) } } impl<'a> From<&'a Keyword> for AnyNodeRef<'a> { @@ -4919,7 +6012,6 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::ModModule(node) => node.range(), AnyNodeRef::ModExpression(node) => node.range(), AnyNodeRef::StmtFunctionDef(node) => node.range(), - AnyNodeRef::StmtAsyncFunctionDef(node) => node.range(), AnyNodeRef::StmtClassDef(node) => node.range(), AnyNodeRef::StmtReturn(node) => node.range(), AnyNodeRef::StmtDelete(node) => node.range(), @@ -4928,15 +6020,12 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::StmtAugAssign(node) => node.range(), AnyNodeRef::StmtAnnAssign(node) => node.range(), AnyNodeRef::StmtFor(node) => node.range(), - AnyNodeRef::StmtAsyncFor(node) => node.range(), AnyNodeRef::StmtWhile(node) => node.range(), AnyNodeRef::StmtIf(node) => node.range(), AnyNodeRef::StmtWith(node) => node.range(), - AnyNodeRef::StmtAsyncWith(node) => node.range(), AnyNodeRef::StmtMatch(node) => node.range(), AnyNodeRef::StmtRaise(node) => node.range(), AnyNodeRef::StmtTry(node) => node.range(), - AnyNodeRef::StmtTryStar(node) => node.range(), AnyNodeRef::StmtAssert(node) => node.range(), AnyNodeRef::StmtImport(node) => node.range(), AnyNodeRef::StmtImportFrom(node) => node.range(), @@ -4946,7 +6035,7 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::StmtPass(node) => node.range(), AnyNodeRef::StmtBreak(node) => node.range(), AnyNodeRef::StmtContinue(node) => node.range(), - AnyNodeRef::StmtLineMagic(node) => node.range(), + AnyNodeRef::StmtIpyEscapeCommand(node) => node.range(), AnyNodeRef::ExprBoolOp(node) => node.range(), AnyNodeRef::ExprNamedExpr(node) => node.range(), AnyNodeRef::ExprBinOp(node) => node.range(), @@ -4965,7 +6054,7 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::ExprCompare(node) => node.range(), AnyNodeRef::ExprCall(node) => node.range(), AnyNodeRef::ExprFormattedValue(node) => node.range(), - AnyNodeRef::ExprJoinedStr(node) => node.range(), + AnyNodeRef::ExprFString(node) => node.range(), AnyNodeRef::ExprConstant(node) => node.range(), AnyNodeRef::ExprAttribute(node) => node.range(), AnyNodeRef::ExprSubscript(node) => node.range(), @@ -4974,7 +6063,7 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::ExprList(node) => node.range(), AnyNodeRef::ExprTuple(node) => node.range(), AnyNodeRef::ExprSlice(node) => node.range(), - AnyNodeRef::ExprLineMagic(node) => node.range(), + AnyNodeRef::ExprIpyEscapeCommand(node) => node.range(), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.range(), AnyNodeRef::PatternMatchValue(node) => node.range(), AnyNodeRef::PatternMatchSingleton(node) => node.range(), @@ -4986,14 +6075,16 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::PatternMatchOr(node) => node.range(), AnyNodeRef::Comprehension(node) => node.range(), AnyNodeRef::Arguments(node) => node.range(), - AnyNodeRef::Arg(node) => node.range(), - AnyNodeRef::ArgWithDefault(node) => node.range(), + AnyNodeRef::Parameters(node) => node.range(), + AnyNodeRef::Parameter(node) => node.range(), + AnyNodeRef::ParameterWithDefault(node) => node.range(), AnyNodeRef::Keyword(node) => node.range(), AnyNodeRef::Alias(node) => node.range(), AnyNodeRef::WithItem(node) => node.range(), AnyNodeRef::MatchCase(node) => node.range(), AnyNodeRef::Decorator(node) => node.range(), AnyNodeRef::ElifElseClause(node) => node.range(), + AnyNodeRef::TypeParams(node) => node.range(), AnyNodeRef::TypeParamTypeVar(node) => node.range(), AnyNodeRef::TypeParamTypeVarTuple(node) => node.range(), AnyNodeRef::TypeParamParamSpec(node) => node.range(), @@ -5008,7 +6099,6 @@ pub enum NodeKind { ModExpression, ModFunctionType, StmtFunctionDef, - StmtAsyncFunctionDef, StmtClassDef, StmtReturn, StmtDelete, @@ -5017,21 +6107,18 @@ pub enum NodeKind { StmtAugAssign, StmtAnnAssign, StmtFor, - StmtAsyncFor, StmtWhile, StmtIf, StmtWith, - StmtAsyncWith, StmtMatch, StmtRaise, StmtTry, - StmtTryStar, StmtAssert, StmtImport, StmtImportFrom, StmtGlobal, StmtNonlocal, - StmtLineMagic, + StmtIpyEscapeCommand, StmtExpr, StmtPass, StmtBreak, @@ -5054,7 +6141,7 @@ pub enum NodeKind { ExprCompare, ExprCall, ExprFormattedValue, - ExprJoinedStr, + ExprFString, ExprConstant, ExprAttribute, ExprSubscript, @@ -5063,7 +6150,7 @@ pub enum NodeKind { ExprList, ExprTuple, ExprSlice, - ExprLineMagic, + ExprIpyEscapeCommand, ExceptHandlerExceptHandler, PatternMatchValue, PatternMatchSingleton, @@ -5076,14 +6163,16 @@ pub enum NodeKind { TypeIgnoreTypeIgnore, Comprehension, Arguments, - Arg, - ArgWithDefault, + Parameters, + Parameter, + ParameterWithDefault, Keyword, Alias, WithItem, MatchCase, Decorator, ElifElseClause, + TypeParams, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParamParamSpec, diff --git a/crates/ruff_python_ast/src/nodes.rs b/crates/ruff_python_ast/src/nodes.rs index 349052d539e78..7e09a2608982f 100644 --- a/crates/ruff_python_ast/src/nodes.rs +++ b/crates/ruff_python_ast/src/nodes.rs @@ -5,6 +5,7 @@ use num_bigint::BigInt; use ruff_text_size::{TextRange, TextSize}; use std::fmt; use std::fmt::Debug; +use std::ops::Deref; /// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -44,8 +45,6 @@ impl From for Mod { pub enum Stmt { #[is(name = "function_def_stmt")] FunctionDef(StmtFunctionDef), - #[is(name = "async_function_def_stmt")] - AsyncFunctionDef(StmtAsyncFunctionDef), #[is(name = "class_def_stmt")] ClassDef(StmtClassDef), #[is(name = "return_stmt")] @@ -62,24 +61,18 @@ pub enum Stmt { TypeAlias(StmtTypeAlias), #[is(name = "for_stmt")] For(StmtFor), - #[is(name = "async_for_stmt")] - AsyncFor(StmtAsyncFor), #[is(name = "while_stmt")] While(StmtWhile), #[is(name = "if_stmt")] If(StmtIf), #[is(name = "with_stmt")] With(StmtWith), - #[is(name = "async_with_stmt")] - AsyncWith(StmtAsyncWith), #[is(name = "match_stmt")] Match(StmtMatch), #[is(name = "raise_stmt")] Raise(StmtRaise), #[is(name = "try_stmt")] Try(StmtTry), - #[is(name = "try_star_stmt")] - TryStar(StmtTryStar), #[is(name = "assert_stmt")] Assert(StmtAssert), #[is(name = "import_stmt")] @@ -100,33 +93,38 @@ pub enum Stmt { Continue(StmtContinue), // Jupyter notebook specific - #[is(name = "line_magic_stmt")] - LineMagic(StmtLineMagic), + #[is(name = "ipy_escape_command_stmt")] + IpyEscapeCommand(StmtIpyEscapeCommand), } #[derive(Clone, Debug, PartialEq)] -pub struct StmtLineMagic { +pub struct StmtIpyEscapeCommand { pub range: TextRange, - pub kind: MagicKind, + pub kind: IpyEscapeKind, pub value: String, } -impl From for Stmt { - fn from(payload: StmtLineMagic) -> Self { - Stmt::LineMagic(payload) +impl From for Stmt { + fn from(payload: StmtIpyEscapeCommand) -> Self { + Stmt::IpyEscapeCommand(payload) } } -/// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef) +/// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef) and +/// [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef). +/// +/// This type differs from the original Python AST, as it collapses the +/// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtFunctionDef { pub range: TextRange, - pub name: Identifier, - pub args: Box, - pub body: Vec, + pub is_async: bool, pub decorator_list: Vec, + pub name: Identifier, + pub type_params: Option, + pub parameters: Box, pub returns: Option>, - pub type_params: Vec, + pub body: Vec, } impl From for Stmt { @@ -135,34 +133,33 @@ impl From for Stmt { } } -/// See also [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef) +/// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef) #[derive(Clone, Debug, PartialEq)] -pub struct StmtAsyncFunctionDef { +pub struct StmtClassDef { pub range: TextRange, + pub decorator_list: Vec, pub name: Identifier, - pub args: Box, + pub type_params: Option>, + pub arguments: Option>, pub body: Vec, - pub decorator_list: Vec, - pub returns: Option>, - pub type_params: Vec, } -impl From for Stmt { - fn from(payload: StmtAsyncFunctionDef) -> Self { - Stmt::AsyncFunctionDef(payload) +impl StmtClassDef { + /// Return an iterator over the bases of the class. + pub fn bases(&self) -> &[Expr] { + match &self.arguments { + Some(arguments) => &arguments.args, + None => &[], + } } -} -/// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef) -#[derive(Clone, Debug, PartialEq)] -pub struct StmtClassDef { - pub range: TextRange, - pub name: Identifier, - pub bases: Vec, - pub keywords: Vec, - pub body: Vec, - pub type_params: Vec, - pub decorator_list: Vec, + /// Return an iterator over the metaclass keywords of the class. + pub fn keywords(&self) -> &[Keyword] { + match &self.arguments { + Some(arguments) => &arguments.keywords, + None => &[], + } + } } impl From for Stmt { @@ -202,7 +199,7 @@ impl From for Stmt { pub struct StmtTypeAlias { pub range: TextRange, pub name: Box, - pub type_params: Vec, + pub type_params: Option, pub value: Box, } @@ -257,10 +254,15 @@ impl From for Stmt { } } -/// See also [For](https://docs.python.org/3/library/ast.html#ast.For) +/// See also [For](https://docs.python.org/3/library/ast.html#ast.For) and +/// [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor). +/// +/// This type differs from the original Python AST, as it collapses the +/// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtFor { pub range: TextRange, + pub is_async: bool, pub target: Box, pub iter: Box, pub body: Vec, @@ -273,23 +275,8 @@ impl From for Stmt { } } -/// See also [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor) -#[derive(Clone, Debug, PartialEq)] -pub struct StmtAsyncFor { - pub range: TextRange, - pub target: Box, - pub iter: Box, - pub body: Vec, - pub orelse: Vec, -} - -impl From for Stmt { - fn from(payload: StmtAsyncFor) -> Self { - Stmt::AsyncFor(payload) - } -} - -/// See also [While](https://docs.python.org/3/library/ast.html#ast.While) +/// See also [While](https://docs.python.org/3/library/ast.html#ast.While) and +/// [AsyncWhile](https://docs.python.org/3/library/ast.html#ast.AsyncWhile). #[derive(Clone, Debug, PartialEq)] pub struct StmtWhile { pub range: TextRange, @@ -326,10 +313,15 @@ pub struct ElifElseClause { pub body: Vec, } -/// See also [With](https://docs.python.org/3/library/ast.html#ast.With) +/// See also [With](https://docs.python.org/3/library/ast.html#ast.With) and +/// [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith). +/// +/// This type differs from the original Python AST, as it collapses the +/// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtWith { pub range: TextRange, + pub is_async: bool, pub items: Vec, pub body: Vec, } @@ -340,20 +332,6 @@ impl From for Stmt { } } -/// See also [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith) -#[derive(Clone, Debug, PartialEq)] -pub struct StmtAsyncWith { - pub range: TextRange, - pub items: Vec, - pub body: Vec, -} - -impl From for Stmt { - fn from(payload: StmtAsyncWith) -> Self { - Stmt::AsyncWith(payload) - } -} - /// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match) #[derive(Clone, Debug, PartialEq)] pub struct StmtMatch { @@ -382,7 +360,8 @@ impl From for Stmt { } } -/// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try) +/// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try) and +/// [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar) #[derive(Clone, Debug, PartialEq)] pub struct StmtTry { pub range: TextRange, @@ -390,6 +369,7 @@ pub struct StmtTry { pub handlers: Vec, pub orelse: Vec, pub finalbody: Vec, + pub is_star: bool, } impl From for Stmt { @@ -398,22 +378,6 @@ impl From for Stmt { } } -/// See also [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar) -#[derive(Clone, Debug, PartialEq)] -pub struct StmtTryStar { - pub range: TextRange, - pub body: Vec, - pub handlers: Vec, - pub orelse: Vec, - pub finalbody: Vec, -} - -impl From for Stmt { - fn from(payload: StmtTryStar) -> Self { - Stmt::TryStar(payload) - } -} - /// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert) #[derive(Clone, Debug, PartialEq)] pub struct StmtAssert { @@ -570,8 +534,8 @@ pub enum Expr { Call(ExprCall), #[is(name = "formatted_value_expr")] FormattedValue(ExprFormattedValue), - #[is(name = "joined_str_expr")] - JoinedStr(ExprJoinedStr), + #[is(name = "f_string_expr")] + FString(ExprFString), #[is(name = "constant_expr")] Constant(ExprConstant), #[is(name = "attribute_expr")] @@ -590,20 +554,20 @@ pub enum Expr { Slice(ExprSlice), // Jupyter notebook specific - #[is(name = "line_magic_expr")] - LineMagic(ExprLineMagic), + #[is(name = "ipy_escape_command_expr")] + IpyEscapeCommand(ExprIpyEscapeCommand), } #[derive(Clone, Debug, PartialEq)] -pub struct ExprLineMagic { +pub struct ExprIpyEscapeCommand { pub range: TextRange, - pub kind: MagicKind, + pub kind: IpyEscapeKind, pub value: String, } -impl From for Expr { - fn from(payload: ExprLineMagic) -> Self { - Expr::LineMagic(payload) +impl From for Expr { + fn from(payload: ExprIpyEscapeCommand) -> Self { + Expr::IpyEscapeCommand(payload) } } @@ -668,7 +632,7 @@ impl From for Expr { #[derive(Clone, Debug, PartialEq)] pub struct ExprLambda { pub range: TextRange, - pub args: Box, + pub parameters: Option>, pub body: Box, } @@ -836,8 +800,7 @@ impl From for Expr { pub struct ExprCall { pub range: TextRange, pub func: Box, - pub args: Vec, - pub keywords: Vec, + pub arguments: Arguments, } impl From for Expr { @@ -899,14 +862,16 @@ pub struct DebugText { /// See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr) #[derive(Clone, Debug, PartialEq)] -pub struct ExprJoinedStr { +pub struct ExprFString { pub range: TextRange, pub values: Vec, + /// Whether the f-string contains multiple string tokens that were implicitly concatenated. + pub implicit_concatenated: bool, } -impl From for Expr { - fn from(payload: ExprJoinedStr) -> Self { - Expr::JoinedStr(payload) +impl From for Expr { + fn from(payload: ExprFString) -> Self { + Expr::FString(payload) } } @@ -1822,24 +1787,11 @@ impl From for ExceptHandler { } } -/// See also [arguments](https://docs.python.org/3/library/ast.html#ast.arguments) -#[derive(Clone, Debug, PartialEq)] -pub struct PythonArguments { - pub range: TextRange, - pub posonlyargs: Vec, - pub args: Vec, - pub vararg: Option>, - pub kwonlyargs: Vec, - pub kw_defaults: Vec, - pub kwarg: Option>, - pub defaults: Vec, -} - /// See also [arg](https://docs.python.org/3/library/ast.html#ast.arg) #[derive(Clone, Debug, PartialEq)] -pub struct Arg { +pub struct Parameter { pub range: TextRange, - pub arg: Identifier, + pub name: Identifier, pub annotation: Option>, } @@ -2056,22 +2008,48 @@ pub struct Decorator { /// An alternative type of AST `arguments`. This is ruff_python_parser-friendly and human-friendly definition of function arguments. /// This form also has advantage to implement pre-order traverse. -/// `defaults` and `kw_defaults` fields are removed and the default values are placed under each `arg_with_default` typed argument. +/// +/// `defaults` and `kw_defaults` fields are removed and the default values are placed under each [`ParameterWithDefault`] typed argument. /// `vararg` and `kwarg` are still typed as `arg` because they never can have a default value. /// -/// The matching Python style AST type is [`PythonArguments`]. While [`PythonArguments`] has ordered `kwonlyargs` fields by -/// default existence, [Arguments] has location-ordered kwonlyargs fields. +/// The original Python-style AST type orders `kwonlyargs` fields by default existence; [Parameters] has location-ordered `kwonlyargs` fields. /// -/// NOTE: This type is different from original Python AST. +/// NOTE: This type differs from the original Python AST. See: [arguments](https://docs.python.org/3/library/ast.html#ast.arguments). #[derive(Clone, Debug, PartialEq)] -pub struct Arguments { +pub struct Parameters { pub range: TextRange, - pub posonlyargs: Vec, - pub args: Vec, - pub vararg: Option>, - pub kwonlyargs: Vec, - pub kwarg: Option>, + pub posonlyargs: Vec, + pub args: Vec, + pub vararg: Option>, + pub kwonlyargs: Vec, + pub kwarg: Option>, +} + +impl Parameters { + /// Returns `true` if a parameter with the given name included in this [`Parameters`]. + pub fn includes(&self, name: &str) -> bool { + if self + .posonlyargs + .iter() + .chain(&self.args) + .chain(&self.kwonlyargs) + .any(|arg| arg.parameter.name.as_str() == name) + { + return true; + } + if let Some(arg) = &self.vararg { + if arg.name.as_str() == name { + return true; + } + } + if let Some(arg) = &self.kwarg { + if arg.name.as_str() == name { + return true; + } + } + false + } } /// An alternative type of AST `arg`. This is used for each function argument that might have a default value. @@ -2080,12 +2058,101 @@ pub struct Arguments { /// NOTE: This type is different from original Python AST. #[derive(Clone, Debug, PartialEq)] -pub struct ArgWithDefault { +pub struct ParameterWithDefault { pub range: TextRange, - pub def: Arg, + pub parameter: Parameter, pub default: Option>, } +/// An AST node used to represent the arguments passed to a function call or class definition. +/// +/// For example, given: +/// ```python +/// foo(1, 2, 3, bar=4, baz=5) +/// ``` +/// The `Arguments` node would span from the left to right parentheses (inclusive), and contain +/// the arguments and keyword arguments in the order they appear in the source code. +/// +/// Similarly, given: +/// ```python +/// class Foo(Bar, baz=1, qux=2): +/// pass +/// ``` +/// The `Arguments` node would again span from the left to right parentheses (inclusive), and +/// contain the `Bar` argument and the `baz` and `qux` keyword arguments in the order they +/// appear in the source code. +/// +/// In the context of a class definition, the Python-style AST refers to the arguments as `bases`, +/// as they represent the "explicitly specified base classes", while the keyword arguments are +/// typically used for `metaclass`, with any additional arguments being passed to the `metaclass`. + +#[derive(Clone, Debug, PartialEq)] +pub struct Arguments { + pub range: TextRange, + pub args: Vec, + pub keywords: Vec, +} + +impl Arguments { + /// Return the number of positional and keyword arguments. + pub fn len(&self) -> usize { + self.args.len() + self.keywords.len() + } + + /// Return `true` if there are no positional or keyword arguments. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Return the [`Keyword`] with the given name, or `None` if no such [`Keyword`] exists. + pub fn find_keyword(&self, keyword_name: &str) -> Option<&Keyword> { + self.keywords.iter().find(|keyword| { + let Keyword { arg, .. } = keyword; + arg.as_ref().is_some_and(|arg| arg == keyword_name) + }) + } + + /// Return the positional argument at the given index, or `None` if no such argument exists. + pub fn find_positional(&self, position: usize) -> Option<&Expr> { + self.args + .iter() + .take_while(|expr| !expr.is_starred_expr()) + .nth(position) + } + + /// Return the argument with the given name or at the given position, or `None` if no such + /// argument exists. Used to retrieve arguments that can be provided _either_ as keyword or + /// positional arguments. + pub fn find_argument(&self, name: &str, position: usize) -> Option<&Expr> { + self.find_keyword(name) + .map(|keyword| &keyword.value) + .or_else(|| self.find_positional(position)) + } +} + +/// An AST node used to represent a sequence of type parameters. +/// +/// For example, given: +/// ```python +/// class C[T, U, V]: ... +/// ``` +/// The `TypeParams` node would span from the left to right brackets (inclusive), and contain +/// the `T`, `U`, and `V` type parameters in the order they appear in the source code. + +#[derive(Clone, Debug, PartialEq)] +pub struct TypeParams { + pub range: TextRange, + pub type_params: Vec, +} + +impl Deref for TypeParams { + type Target = [TypeParam]; + + fn deref(&self) -> &Self::Target { + &self.type_params + } +} + pub type Suite = Vec; impl CmpOp { @@ -2105,7 +2172,7 @@ impl CmpOp { } } -impl Arguments { +impl Parameters { pub fn empty(range: TextRange) -> Self { Self { range, @@ -2124,30 +2191,30 @@ fn clone_boxed_expr(expr: &Box) -> Box { Box::new(expr.clone()) } -impl ArgWithDefault { - pub fn as_arg(&self) -> &Arg { - &self.def +impl ParameterWithDefault { + pub fn as_parameter(&self) -> &Parameter { + &self.parameter } - pub fn to_arg(&self) -> (Arg, Option>) { - let ArgWithDefault { + pub fn to_parameter(&self) -> (Parameter, Option>) { + let ParameterWithDefault { range: _, - def, + parameter, default, } = self; - (def.clone(), default.as_ref().map(clone_boxed_expr)) + (parameter.clone(), default.as_ref().map(clone_boxed_expr)) } - pub fn into_arg(self) -> (Arg, Option>) { - let ArgWithDefault { + pub fn into_parameter(self) -> (Parameter, Option>) { + let ParameterWithDefault { range: _, - def, + parameter, default, } = self; - (def, default) + (parameter, default) } } -impl Arguments { +impl Parameters { pub fn defaults(&self) -> impl std::iter::Iterator { self.posonlyargs .iter() @@ -2156,105 +2223,119 @@ impl Arguments { } #[allow(clippy::type_complexity)] - pub fn split_kwonlyargs(&self) -> (Vec<&Arg>, Vec<(&Arg, &Expr)>) { + pub fn split_kwonlyargs(&self) -> (Vec<&Parameter>, Vec<(&Parameter, &Expr)>) { let mut args = Vec::new(); let mut with_defaults = Vec::new(); for arg in &self.kwonlyargs { if let Some(ref default) = arg.default { - with_defaults.push((arg.as_arg(), &**default)); + with_defaults.push((arg.as_parameter(), &**default)); } else { - args.push(arg.as_arg()); + args.push(arg.as_parameter()); } } (args, with_defaults) } } -/// The kind of magic command as defined in [IPython Syntax] in the IPython codebase. +/// The kind of escape command as defined in [IPython Syntax] in the IPython codebase. /// /// [IPython Syntax]: https://github.com/ipython/ipython/blob/635815e8f1ded5b764d66cacc80bbe25e9e2587f/IPython/core/inputtransformer2.py#L335-L343 #[derive(PartialEq, Eq, Debug, Clone, Hash, Copy)] -pub enum MagicKind { - /// Send line to underlying system shell. +pub enum IpyEscapeKind { + /// Send line to underlying system shell (`!`). Shell, - /// Send line to system shell and capture output. + /// Send line to system shell and capture output (`!!`). ShCap, - /// Show help on object. + /// Show help on object (`?`). Help, - /// Show help on object, with extra verbosity. + /// Show help on object, with extra verbosity (`??`). Help2, - /// Call magic function. + /// Call magic function (`%`). Magic, - /// Call cell magic function. + /// Call cell magic function (`%%`). Magic2, /// Call first argument with rest of line as arguments after splitting on whitespace - /// and quote each as string. + /// and quote each as string (`,`). Quote, - /// Call first argument with rest of line as an argument quoted as a single string. + /// Call first argument with rest of line as an argument quoted as a single string (`;`). Quote2, - /// Call first argument with rest of line as arguments. + /// Call first argument with rest of line as arguments (`/`). Paren, } -impl TryFrom for MagicKind { +impl TryFrom for IpyEscapeKind { type Error = String; fn try_from(ch: char) -> Result { match ch { - '!' => Ok(MagicKind::Shell), - '?' => Ok(MagicKind::Help), - '%' => Ok(MagicKind::Magic), - ',' => Ok(MagicKind::Quote), - ';' => Ok(MagicKind::Quote2), - '/' => Ok(MagicKind::Paren), + '!' => Ok(IpyEscapeKind::Shell), + '?' => Ok(IpyEscapeKind::Help), + '%' => Ok(IpyEscapeKind::Magic), + ',' => Ok(IpyEscapeKind::Quote), + ';' => Ok(IpyEscapeKind::Quote2), + '/' => Ok(IpyEscapeKind::Paren), _ => Err(format!("Unexpected magic escape: {ch}")), } } } -impl TryFrom<[char; 2]> for MagicKind { +impl TryFrom<[char; 2]> for IpyEscapeKind { type Error = String; fn try_from(ch: [char; 2]) -> Result { match ch { - ['!', '!'] => Ok(MagicKind::ShCap), - ['?', '?'] => Ok(MagicKind::Help2), - ['%', '%'] => Ok(MagicKind::Magic2), + ['!', '!'] => Ok(IpyEscapeKind::ShCap), + ['?', '?'] => Ok(IpyEscapeKind::Help2), + ['%', '%'] => Ok(IpyEscapeKind::Magic2), [c1, c2] => Err(format!("Unexpected magic escape: {c1}{c2}")), } } } -impl fmt::Display for MagicKind { +impl fmt::Display for IpyEscapeKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - MagicKind::Shell => f.write_str("!"), - MagicKind::ShCap => f.write_str("!!"), - MagicKind::Help => f.write_str("?"), - MagicKind::Help2 => f.write_str("??"), - MagicKind::Magic => f.write_str("%"), - MagicKind::Magic2 => f.write_str("%%"), - MagicKind::Quote => f.write_str(","), - MagicKind::Quote2 => f.write_str(";"), - MagicKind::Paren => f.write_str("/"), - } + f.write_str(self.as_str()) } } -impl MagicKind { - /// Returns the length of the magic command prefix. +impl IpyEscapeKind { + /// Returns the length of the escape kind token. pub fn prefix_len(self) -> TextSize { let len = match self { - MagicKind::Shell - | MagicKind::Magic - | MagicKind::Help - | MagicKind::Quote - | MagicKind::Quote2 - | MagicKind::Paren => 1, - MagicKind::ShCap | MagicKind::Magic2 | MagicKind::Help2 => 2, + IpyEscapeKind::Shell + | IpyEscapeKind::Magic + | IpyEscapeKind::Help + | IpyEscapeKind::Quote + | IpyEscapeKind::Quote2 + | IpyEscapeKind::Paren => 1, + IpyEscapeKind::ShCap | IpyEscapeKind::Magic2 | IpyEscapeKind::Help2 => 2, }; len.into() } + + /// Returns `true` if the escape kind is help i.e., `?` or `??`. + pub const fn is_help(self) -> bool { + matches!(self, IpyEscapeKind::Help | IpyEscapeKind::Help2) + } + + /// Returns `true` if the escape kind is magic i.e., `%` or `%%`. + pub const fn is_magic(self) -> bool { + matches!(self, IpyEscapeKind::Magic | IpyEscapeKind::Magic2) + } + + pub fn as_str(self) -> &'static str { + match self { + IpyEscapeKind::Shell => "!", + IpyEscapeKind::ShCap => "!!", + IpyEscapeKind::Help => "?", + IpyEscapeKind::Help2 => "??", + IpyEscapeKind::Magic => "%", + IpyEscapeKind::Magic2 => "%%", + IpyEscapeKind::Quote => ",", + IpyEscapeKind::Quote2 => ";", + IpyEscapeKind::Paren => "/", + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -2368,8 +2449,8 @@ impl std::cmp::PartialEq for Int { pub enum Constant { None, Bool(bool), - Str(String), - Bytes(Vec), + Str(StringConstant), + Bytes(BytesConstant), Int(BigInt), Float(f64), Complex { real: f64, imag: f64 }, @@ -2377,38 +2458,68 @@ pub enum Constant { } impl Constant { - pub fn is_true(self) -> bool { - self.bool().map_or(false, |b| b) - } - pub fn is_false(self) -> bool { - self.bool().map_or(false, |b| !b) - } - pub fn complex(self) -> Option<(f64, f64)> { + /// Returns `true` if the constant is a string or bytes constant that contains multiple, + /// implicitly concatenated string tokens. + pub fn is_implicit_concatenated(&self) -> bool { match self { - Constant::Complex { real, imag } => Some((real, imag)), - _ => None, + Constant::Str(value) => value.implicit_concatenated, + Constant::Bytes(value) => value.implicit_concatenated, + _ => false, } } } -impl From for Constant { - fn from(s: String) -> Constant { - Self::Str(s) +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StringConstant { + /// The string value as resolved by the parser (i.e., without quotes, or escape sequences, or + /// implicit concatenations). + pub value: String, + /// Whether the string contains multiple string tokens that were implicitly concatenated. + pub implicit_concatenated: bool, +} + +impl Deref for StringConstant { + type Target = str; + fn deref(&self) -> &Self::Target { + self.value.as_str() + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BytesConstant { + /// The bytes value as resolved by the parser (i.e., without quotes, or escape sequences, or + /// implicit concatenations). + pub value: Vec, + /// Whether the string contains multiple string tokens that were implicitly concatenated. + pub implicit_concatenated: bool, +} + +impl Deref for BytesConstant { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + self.value.as_slice() } } + impl From> for Constant { - fn from(b: Vec) -> Constant { - Self::Bytes(b) + fn from(value: Vec) -> Constant { + Self::Bytes(BytesConstant { + value, + implicit_concatenated: false, + }) } } -impl From for Constant { - fn from(b: bool) -> Constant { - Self::Bool(b) +impl From for Constant { + fn from(value: String) -> Constant { + Self::Str(StringConstant { + value, + implicit_concatenated: false, + }) } } -impl From for Constant { - fn from(i: BigInt) -> Constant { - Self::Int(i) +impl From for Constant { + fn from(value: bool) -> Constant { + Self::Bool(value) } } @@ -2464,11 +2575,6 @@ impl Ranged for crate::nodes::StmtFunctionDef { self.range } } -impl Ranged for crate::nodes::StmtAsyncFunctionDef { - fn range(&self) -> TextRange { - self.range - } -} impl Ranged for crate::nodes::StmtClassDef { fn range(&self) -> TextRange { self.range @@ -2509,11 +2615,6 @@ impl Ranged for crate::nodes::StmtFor { self.range } } -impl Ranged for crate::nodes::StmtAsyncFor { - fn range(&self) -> TextRange { - self.range - } -} impl Ranged for crate::nodes::StmtWhile { fn range(&self) -> TextRange { self.range @@ -2534,11 +2635,6 @@ impl Ranged for crate::nodes::StmtWith { self.range } } -impl Ranged for crate::nodes::StmtAsyncWith { - fn range(&self) -> TextRange { - self.range - } -} impl Ranged for crate::nodes::StmtMatch { fn range(&self) -> TextRange { self.range @@ -2554,11 +2650,6 @@ impl Ranged for crate::nodes::StmtTry { self.range } } -impl Ranged for crate::nodes::StmtTryStar { - fn range(&self) -> TextRange { - self.range - } -} impl Ranged for crate::nodes::StmtAssert { fn range(&self) -> TextRange { self.range @@ -2604,7 +2695,7 @@ impl Ranged for crate::nodes::StmtContinue { self.range } } -impl Ranged for StmtLineMagic { +impl Ranged for StmtIpyEscapeCommand { fn range(&self) -> TextRange { self.range } @@ -2613,7 +2704,6 @@ impl Ranged for crate::Stmt { fn range(&self) -> TextRange { match self { Self::FunctionDef(node) => node.range(), - Self::AsyncFunctionDef(node) => node.range(), Self::ClassDef(node) => node.range(), Self::Return(node) => node.range(), Self::Delete(node) => node.range(), @@ -2622,15 +2712,12 @@ impl Ranged for crate::Stmt { Self::AugAssign(node) => node.range(), Self::AnnAssign(node) => node.range(), Self::For(node) => node.range(), - Self::AsyncFor(node) => node.range(), Self::While(node) => node.range(), Self::If(node) => node.range(), Self::With(node) => node.range(), - Self::AsyncWith(node) => node.range(), Self::Match(node) => node.range(), Self::Raise(node) => node.range(), Self::Try(node) => node.range(), - Self::TryStar(node) => node.range(), Self::Assert(node) => node.range(), Self::Import(node) => node.range(), Self::ImportFrom(node) => node.range(), @@ -2640,7 +2727,7 @@ impl Ranged for crate::Stmt { Self::Pass(node) => node.range(), Self::Break(node) => node.range(), Self::Continue(node) => node.range(), - Stmt::LineMagic(node) => node.range(), + Stmt::IpyEscapeCommand(node) => node.range(), } } } @@ -2735,7 +2822,7 @@ impl Ranged for crate::nodes::ExprFormattedValue { self.range } } -impl Ranged for crate::nodes::ExprJoinedStr { +impl Ranged for crate::nodes::ExprFString { fn range(&self) -> TextRange { self.range } @@ -2780,7 +2867,7 @@ impl Ranged for crate::nodes::ExprSlice { self.range } } -impl Ranged for ExprLineMagic { +impl Ranged for ExprIpyEscapeCommand { fn range(&self) -> TextRange { self.range } @@ -2806,7 +2893,7 @@ impl Ranged for crate::Expr { Self::Compare(node) => node.range(), Self::Call(node) => node.range(), Self::FormattedValue(node) => node.range(), - Self::JoinedStr(node) => node.range(), + Self::FString(node) => node.range(), Self::Constant(node) => node.range(), Self::Attribute(node) => node.range(), Self::Subscript(node) => node.range(), @@ -2815,7 +2902,7 @@ impl Ranged for crate::Expr { Self::List(node) => node.range(), Self::Tuple(node) => node.range(), Self::Slice(node) => node.range(), - Expr::LineMagic(node) => node.range(), + Expr::IpyEscapeCommand(node) => node.range(), } } } @@ -2838,12 +2925,7 @@ impl Ranged for crate::ExceptHandler { } } -impl Ranged for crate::nodes::PythonArguments { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::nodes::Arg { +impl Ranged for crate::nodes::Parameter { fn range(&self) -> TextRange { self.range } @@ -2923,6 +3005,11 @@ impl Ranged for crate::Pattern { } } +impl Ranged for crate::nodes::TypeParams { + fn range(&self) -> TextRange { + self.range + } +} impl Ranged for crate::nodes::TypeParamTypeVar { fn range(&self) -> TextRange { self.range @@ -2957,7 +3044,12 @@ impl Ranged for crate::nodes::Arguments { self.range } } -impl Ranged for crate::nodes::ArgWithDefault { +impl Ranged for crate::nodes::Parameters { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ParameterWithDefault { fn range(&self) -> TextRange { self.range } @@ -2969,12 +3061,12 @@ mod size_assertions { use super::*; use static_assertions::assert_eq_size; - assert_eq_size!(Stmt, [u8; 168]); - assert_eq_size!(StmtFunctionDef, [u8; 128]); - assert_eq_size!(StmtClassDef, [u8; 160]); - assert_eq_size!(StmtTry, [u8; 104]); + assert_eq_size!(Stmt, [u8; 144]); + assert_eq_size!(StmtFunctionDef, [u8; 144]); + assert_eq_size!(StmtClassDef, [u8; 104]); + assert_eq_size!(StmtTry, [u8; 112]); assert_eq_size!(Expr, [u8; 80]); - assert_eq_size!(Constant, [u8; 32]); + assert_eq_size!(Constant, [u8; 40]); assert_eq_size!(Pattern, [u8; 96]); assert_eq_size!(Mod, [u8; 32]); } diff --git a/crates/ruff_python_ast/src/parenthesize.rs b/crates/ruff_python_ast/src/parenthesize.rs new file mode 100644 index 0000000000000..e8dfee57762c9 --- /dev/null +++ b/crates/ruff_python_ast/src/parenthesize.rs @@ -0,0 +1,48 @@ +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::{TextRange, TextSize}; + +use crate::node::AnyNodeRef; +use crate::{ExpressionRef, Ranged}; + +/// Returns the [`TextRange`] of a given expression including parentheses, if the expression is +/// parenthesized; or `None`, if the expression is not parenthesized. +pub fn parenthesized_range( + expr: ExpressionRef, + parent: AnyNodeRef, + source: &str, +) -> Option { + // If the parent is a node that brings its own parentheses, exclude the closing parenthesis + // from our search range. Otherwise, we risk matching on calls, like `func(x)`, for which + // the open and close parentheses are part of the `Arguments` node. + // + // There are a few other nodes that may have their own parentheses, but are fine to exclude: + // - `Parameters`: The parameters to a function definition. Any expressions would represent + // default arguments, and so must be preceded by _at least_ the parameter name. As such, + // we won't mistake any parentheses for the opening and closing parentheses on the + // `Parameters` node itself. + // - `Tuple`: The elements of a tuple. The only risk is a single-element tuple (e.g., `(x,)`), + // which must have a trailing comma anyway. + let exclusive_parent_end = if parent.is_arguments() { + parent.end() - TextSize::new(1) + } else { + parent.end() + }; + + let right_tokenizer = + SimpleTokenizer::new(source, TextRange::new(expr.end(), exclusive_parent_end)) + .skip_trivia() + .take_while(|token| token.kind == SimpleTokenKind::RParen); + + let left_tokenizer = SimpleTokenizer::up_to_without_back_comment(expr.start(), source) + .skip_trivia() + .rev() + .take_while(|token| token.kind == SimpleTokenKind::LParen); + + // Zip closing parenthesis with opening parenthesis. The order is intentional, as testing for + // closing parentheses is cheaper, and `zip` will avoid progressing the `left_tokenizer` if + // the `right_tokenizer` is exhausted. + right_tokenizer + .zip(left_tokenizer) + .last() + .map(|(right, left)| TextRange::new(left.start(), right.end())) +} diff --git a/crates/ruff_python_ast/src/relocate.rs b/crates/ruff_python_ast/src/relocate.rs index 8ee02fe8fcbd2..122cdbc259ba0 100644 --- a/crates/ruff_python_ast/src/relocate.rs +++ b/crates/ruff_python_ast/src/relocate.rs @@ -1,4 +1,4 @@ -use crate::{nodes, Expr, Keyword}; +use crate::{nodes, Arguments, Expr, Keyword}; use ruff_text_size::TextRange; fn relocate_keyword(keyword: &mut Keyword, location: TextRange) { @@ -116,8 +116,7 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { } Expr::Call(nodes::ExprCall { func, - args, - keywords, + arguments: Arguments { args, keywords, .. }, range, }) => { *range = location; @@ -141,7 +140,7 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { relocate_expr(expr, location); } } - Expr::JoinedStr(nodes::ExprJoinedStr { values, range }) => { + Expr::FString(nodes::ExprFString { values, range, .. }) => { *range = location; for expr in values { relocate_expr(expr, location); @@ -200,7 +199,7 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { relocate_expr(expr, location); } } - Expr::LineMagic(nodes::ExprLineMagic { range, .. }) => { + Expr::IpyEscapeCommand(nodes::ExprIpyEscapeCommand { range, .. }) => { *range = location; } } diff --git a/crates/ruff_python_ast/src/statement_visitor.rs b/crates/ruff_python_ast/src/statement_visitor.rs index 7b493b2043861..7ab3ebe06c4e9 100644 --- a/crates/ruff_python_ast/src/statement_visitor.rs +++ b/crates/ruff_python_ast/src/statement_visitor.rs @@ -32,9 +32,6 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &' Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => { visitor.visit_body(body); } - Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => { - visitor.visit_body(body); - } Stmt::For(ast::StmtFor { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); @@ -42,10 +39,6 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &' Stmt::ClassDef(ast::StmtClassDef { body, .. }) => { visitor.visit_body(body); } - Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { - visitor.visit_body(body); - visitor.visit_body(orelse); - } Stmt::While(ast::StmtWhile { body, orelse, .. }) => { visitor.visit_body(body); visitor.visit_body(orelse); @@ -63,9 +56,6 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &' Stmt::With(ast::StmtWith { body, .. }) => { visitor.visit_body(body); } - Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => { - visitor.visit_body(body); - } Stmt::Match(ast::StmtMatch { cases, .. }) => { for match_case in cases { visitor.visit_match_case(match_case); @@ -76,21 +66,7 @@ pub fn walk_stmt<'a, V: StatementVisitor<'a> + ?Sized>(visitor: &mut V, stmt: &' handlers, orelse, finalbody, - range: _range, - }) => { - visitor.visit_body(body); - for except_handler in handlers { - visitor.visit_except_handler(except_handler); - } - visitor.visit_body(orelse); - visitor.visit_body(finalbody); - } - Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, + .. }) => { visitor.visit_body(body); for except_handler in handlers { diff --git a/crates/ruff_python_ast/src/stmt_if.rs b/crates/ruff_python_ast/src/stmt_if.rs index 0acc04a40535f..c8a1e34e836ce 100644 --- a/crates/ruff_python_ast/src/stmt_if.rs +++ b/crates/ruff_python_ast/src/stmt_if.rs @@ -24,6 +24,12 @@ pub struct IfElifBranch<'a> { pub range: TextRange, } +impl Ranged for IfElifBranch<'_> { + fn range(&self) -> TextRange { + self.range + } +} + pub fn if_elif_branches(stmt_if: &StmtIf) -> impl Iterator { iter::once(IfElifBranch { kind: BranchKind::If, @@ -40,6 +46,3 @@ pub fn if_elif_branches(stmt_if: &StmtIf) -> impl Iterator }) })) } - -#[cfg(test)] -mod test {} diff --git a/crates/ruff_python_ast/src/str.rs b/crates/ruff_python_ast/src/str.rs index 5421641c2169d..8ddff85958994 100644 --- a/crates/ruff_python_ast/src/str.rs +++ b/crates/ruff_python_ast/src/str.rs @@ -184,68 +184,8 @@ pub fn is_triple_quote(content: &str) -> bool { TRIPLE_QUOTE_STR_PREFIXES.contains(&content) || TRIPLE_QUOTE_BYTE_PREFIXES.contains(&content) } -/// Return `true` if the string expression is an implicit concatenation. -/// -/// ## Examples -/// -/// ```rust -/// use ruff_python_ast::str::is_implicit_concatenation; -/// -/// assert!(is_implicit_concatenation(r#"'abc' 'def'"#)); -/// assert!(!is_implicit_concatenation(r#"'abcdef'"#)); -/// ``` -pub fn is_implicit_concatenation(content: &str) -> bool { - let Some(leading_quote_str) = leading_quote(content) else { - return false; - }; - let Some(trailing_quote_str) = trailing_quote(content) else { - return false; - }; - - // If the trailing quote doesn't match the _expected_ trailing quote, then the string is - // implicitly concatenated. - // - // For example, given: - // ```python - // u"""abc""" 'def' - // ``` - // - // The leading quote would be `u"""`, and the trailing quote would be `'`, but the _expected_ - // trailing quote would be `"""`. Since `'` does not equal `"""`, we'd return `true`. - if trailing_quote_str != trailing_quote(leading_quote_str).unwrap() { - return true; - } - - // Search for any trailing quotes _before_ the end of the string. - let mut rest = &content[leading_quote_str.len()..content.len() - trailing_quote_str.len()]; - while let Some(index) = rest.find(trailing_quote_str) { - let mut chars = rest[..index].chars().rev(); - - if let Some('\\') = chars.next() { - if chars.next() == Some('\\') { - // Either `\\'` or `\\\'` need to test one more character - - // If the quote is preceded by `//` then it is not escaped, instead the backslash is escaped. - if chars.next() != Some('\\') { - return true; - } - } - } else { - // If the quote is _not_ escaped, then it's implicitly concatenated. - return true; - } - rest = &rest[index + trailing_quote_str.len()..]; - } - - // Otherwise, we know the string ends with the expected trailing quote, so it's not implicitly - // concatenated. - false -} - #[cfg(test)] mod tests { - use crate::str::is_implicit_concatenation; - use super::{ SINGLE_QUOTE_BYTE_PREFIXES, SINGLE_QUOTE_STR_PREFIXES, TRIPLE_QUOTE_BYTE_PREFIXES, TRIPLE_QUOTE_STR_PREFIXES, @@ -270,39 +210,4 @@ mod tests { } } } - - #[test] - fn implicit_concatenation() { - // Positive cases. - assert!(is_implicit_concatenation(r#""abc" "def""#)); - assert!(is_implicit_concatenation(r#""abc" 'def'"#)); - assert!(is_implicit_concatenation(r#""""abc""" "def""#)); - assert!(is_implicit_concatenation(r#"'''abc''' 'def'"#)); - assert!(is_implicit_concatenation(r#""""abc""" 'def'"#)); - assert!(is_implicit_concatenation(r#"'''abc''' "def""#)); - assert!(is_implicit_concatenation(r#""""abc""""def""#)); - assert!(is_implicit_concatenation(r#"'''abc''''def'"#)); - assert!(is_implicit_concatenation(r#""""abc"""'def'"#)); - assert!(is_implicit_concatenation(r#"'''abc'''"def""#)); - - // Negative cases. - assert!(!is_implicit_concatenation(r#""abc""#)); - assert!(!is_implicit_concatenation(r#"'abc'"#)); - assert!(!is_implicit_concatenation(r#""""abc""""#)); - assert!(!is_implicit_concatenation(r#"'''abc'''"#)); - assert!(!is_implicit_concatenation(r#""""ab"c""""#)); - assert!(!is_implicit_concatenation(r#"'''ab'c'''"#)); - assert!(!is_implicit_concatenation(r#""""ab'c""""#)); - assert!(!is_implicit_concatenation(r#"'''ab"c'''"#)); - assert!(!is_implicit_concatenation(r#""""ab'''c""""#)); - assert!(!is_implicit_concatenation(r#"'''ab"""c'''"#)); - - // Positive cases with escaped quotes. - assert!(is_implicit_concatenation(r#""abc\\""def""#)); - assert!(is_implicit_concatenation(r#""abc\\""def""#)); - - // Negative cases with escaped quotes. - assert!(!is_implicit_concatenation(r#""abc\"def""#)); - assert!(!is_implicit_concatenation(r#"'\\\' ""'"#)); - } } diff --git a/crates/ruff_python_ast/src/traversal.rs b/crates/ruff_python_ast/src/traversal.rs index 95f88d13c96cc..d89e29484b2ae 100644 --- a/crates/ruff_python_ast/src/traversal.rs +++ b/crates/ruff_python_ast/src/traversal.rs @@ -5,7 +5,6 @@ use crate::{self as ast, ExceptHandler, Stmt, Suite}; pub fn suite<'a>(stmt: &'a Stmt, parent: &'a Stmt) -> Option<&'a Suite> { match parent { Stmt::FunctionDef(ast::StmtFunctionDef { body, .. }) => Some(body), - Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) => Some(body), Stmt::ClassDef(ast::StmtClassDef { body, .. }) => Some(body), Stmt::For(ast::StmtFor { body, orelse, .. }) => { if body.contains(stmt) { @@ -16,15 +15,6 @@ pub fn suite<'a>(stmt: &'a Stmt, parent: &'a Stmt) -> Option<&'a Suite> { None } } - Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. }) => { - if body.contains(stmt) { - Some(body) - } else if orelse.contains(stmt) { - Some(orelse) - } else { - None - } - } Stmt::While(ast::StmtWhile { body, orelse, .. }) => { if body.contains(stmt) { Some(body) @@ -49,7 +39,6 @@ pub fn suite<'a>(stmt: &'a Stmt, parent: &'a Stmt) -> Option<&'a Suite> { } } Stmt::With(ast::StmtWith { body, .. }) => Some(body), - Stmt::AsyncWith(ast::StmtAsyncWith { body, .. }) => Some(body), Stmt::Match(ast::StmtMatch { cases, .. }) => cases .iter() .map(|case| &case.body) @@ -75,27 +64,6 @@ pub fn suite<'a>(stmt: &'a Stmt, parent: &'a Stmt) -> Option<&'a Suite> { .find(|body| body.contains(stmt)) } } - Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - .. - }) => { - if body.contains(stmt) { - Some(body) - } else if orelse.contains(stmt) { - Some(orelse) - } else if finalbody.contains(stmt) { - Some(finalbody) - } else { - handlers - .iter() - .filter_map(ExceptHandler::as_except_handler) - .map(|handler| &handler.body) - .find(|body| body.contains(stmt)) - } - } _ => None, } } diff --git a/crates/ruff_python_ast/src/types.rs b/crates/ruff_python_ast/src/types.rs index 5243f94b425fd..32732ed6cbf0c 100644 --- a/crates/ruff_python_ast/src/types.rs +++ b/crates/ruff_python_ast/src/types.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use crate::{Expr, Stmt}; #[derive(Clone)] @@ -7,78 +5,3 @@ pub enum Node<'a> { Stmt(&'a Stmt), Expr(&'a Expr), } - -#[derive(Debug)] -pub struct RefEquality<'a, T>(pub &'a T); - -impl<'a, T> RefEquality<'a, T> { - // More specific implementation that keeps the `'a` lifetime. - // It's otherwise the same as [`AsRef::as_ref`] - #[allow(clippy::should_implement_trait)] - pub fn as_ref(&self) -> &'a T { - self.0 - } -} - -impl<'a, T> AsRef for RefEquality<'a, T> { - fn as_ref(&self) -> &T { - self.0 - } -} - -impl<'a, T> Clone for RefEquality<'a, T> { - fn clone(&self) -> Self { - *self - } -} - -impl<'a, T> Copy for RefEquality<'a, T> {} - -impl<'a, T> std::hash::Hash for RefEquality<'a, T> { - fn hash(&self, state: &mut H) - where - H: std::hash::Hasher, - { - (self.0 as *const T).hash(state); - } -} - -impl<'a, 'b, T> PartialEq> for RefEquality<'a, T> { - fn eq(&self, other: &RefEquality<'b, T>) -> bool { - std::ptr::eq(self.0, other.0) - } -} - -impl<'a, T> Eq for RefEquality<'a, T> {} - -impl<'a, T> Deref for RefEquality<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - self.0 - } -} - -impl<'a> From<&RefEquality<'a, Stmt>> for &'a Stmt { - fn from(r: &RefEquality<'a, Stmt>) -> Self { - r.0 - } -} - -impl<'a> From<&RefEquality<'a, Expr>> for &'a Expr { - fn from(r: &RefEquality<'a, Expr>) -> Self { - r.0 - } -} - -impl<'a> From> for &'a Stmt { - fn from(r: RefEquality<'a, Stmt>) -> Self { - r.0 - } -} - -impl<'a> From> for &'a Expr { - fn from(r: RefEquality<'a, Expr>) -> Self { - r.0 - } -} diff --git a/crates/ruff_python_ast/src/visitor.rs b/crates/ruff_python_ast/src/visitor.rs index 362233c7dd28d..be51dda0663a1 100644 --- a/crates/ruff_python_ast/src/visitor.rs +++ b/crates/ruff_python_ast/src/visitor.rs @@ -3,9 +3,9 @@ pub mod preorder; use crate::{ - self as ast, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Decorator, ElifElseClause, - ExceptHandler, Expr, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, TypeParam, - TypeParamTypeVar, UnaryOp, WithItem, + self as ast, Alias, Arguments, BoolOp, CmpOp, Comprehension, Decorator, ElifElseClause, + ExceptHandler, Expr, ExprContext, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, + Stmt, TypeParam, TypeParamTypeVar, TypeParams, UnaryOp, WithItem, }; /// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order. @@ -55,8 +55,11 @@ pub trait Visitor<'a> { fn visit_arguments(&mut self, arguments: &'a Arguments) { walk_arguments(self, arguments); } - fn visit_arg(&mut self, arg: &'a Arg) { - walk_arg(self, arg); + fn visit_parameters(&mut self, parameters: &'a Parameters) { + walk_parameters(self, parameters); + } + fn visit_parameter(&mut self, parameter: &'a Parameter) { + walk_parameter(self, parameter); } fn visit_keyword(&mut self, keyword: &'a Keyword) { walk_keyword(self, keyword); @@ -67,6 +70,9 @@ pub trait Visitor<'a> { fn visit_with_item(&mut self, with_item: &'a WithItem) { walk_with_item(self, with_item); } + fn visit_type_params(&mut self, type_params: &'a TypeParams) { + walk_type_params(self, type_params); + } fn visit_type_param(&mut self, type_param: &'a TypeParam) { walk_type_param(self, type_param); } @@ -103,27 +109,7 @@ pub fn walk_elif_else_clause<'a, V: Visitor<'a> + ?Sized>( pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { match stmt { Stmt::FunctionDef(ast::StmtFunctionDef { - args, - body, - decorator_list, - returns, - type_params, - .. - }) => { - for decorator in decorator_list { - visitor.visit_decorator(decorator); - } - for type_param in type_params { - visitor.visit_type_param(type_param); - } - visitor.visit_arguments(args); - for expr in returns { - visitor.visit_annotation(expr); - } - visitor.visit_body(body); - } - Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - args, + parameters, body, decorator_list, returns, @@ -133,18 +119,17 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { for decorator in decorator_list { visitor.visit_decorator(decorator); } - for type_param in type_params { - visitor.visit_type_param(type_param); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); } - visitor.visit_arguments(args); + visitor.visit_parameters(parameters); for expr in returns { visitor.visit_annotation(expr); } visitor.visit_body(body); } Stmt::ClassDef(ast::StmtClassDef { - bases, - keywords, + arguments, body, decorator_list, type_params, @@ -153,42 +138,33 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { for decorator in decorator_list { visitor.visit_decorator(decorator); } - for type_param in type_params { - visitor.visit_type_param(type_param); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); } - for expr in bases { - visitor.visit_expr(expr); - } - for keyword in keywords { - visitor.visit_keyword(keyword); + if let Some(arguments) = arguments { + visitor.visit_arguments(arguments); } visitor.visit_body(body); } - Stmt::Return(ast::StmtReturn { - value, - range: _range, - }) => { + Stmt::Return(ast::StmtReturn { value, range: _ }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } - Stmt::Delete(ast::StmtDelete { - targets, - range: _range, - }) => { + Stmt::Delete(ast::StmtDelete { targets, range: _ }) => { for expr in targets { visitor.visit_expr(expr); } } Stmt::TypeAlias(ast::StmtTypeAlias { - range: _range, + range: _, name, type_params, value, }) => { visitor.visit_expr(value); - for type_param in type_params { - visitor.visit_type_param(type_param); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); } visitor.visit_expr(name); } @@ -202,7 +178,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { target, op, value, - range: _range, + range: _, }) => { visitor.visit_expr(value); visitor.visit_operator(op); @@ -232,23 +208,11 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { visitor.visit_body(body); visitor.visit_body(orelse); } - Stmt::AsyncFor(ast::StmtAsyncFor { - target, - iter, - body, - orelse, - .. - }) => { - visitor.visit_expr(iter); - visitor.visit_expr(target); - visitor.visit_body(body); - visitor.visit_body(orelse); - } Stmt::While(ast::StmtWhile { test, body, orelse, - range: _range, + range: _, }) => { visitor.visit_expr(test); visitor.visit_body(body); @@ -258,7 +222,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { test, body, elif_else_clauses, - range: _range, + range: _, }) => { visitor.visit_expr(test); visitor.visit_body(body); @@ -275,16 +239,10 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } visitor.visit_body(body); } - Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { - for with_item in items { - visitor.visit_with_item(with_item); - } - visitor.visit_body(body); - } Stmt::Match(ast::StmtMatch { subject, cases, - range: _range, + range: _, }) => { visitor.visit_expr(subject); for match_case in cases { @@ -294,7 +252,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { Stmt::Raise(ast::StmtRaise { exc, cause, - range: _range, + range: _, }) => { if let Some(expr) = exc { visitor.visit_expr(expr); @@ -308,21 +266,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { handlers, orelse, finalbody, - range: _range, - }) => { - visitor.visit_body(body); - for except_handler in handlers { - visitor.visit_except_handler(except_handler); - } - visitor.visit_body(orelse); - visitor.visit_body(finalbody); - } - Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, + is_star: _, + range: _, }) => { visitor.visit_body(body); for except_handler in handlers { @@ -334,17 +279,14 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { Stmt::Assert(ast::StmtAssert { test, msg, - range: _range, + range: _, }) => { visitor.visit_expr(test); if let Some(expr) = msg { visitor.visit_expr(expr); } } - Stmt::Import(ast::StmtImport { - names, - range: _range, - }) => { + Stmt::Import(ast::StmtImport { names, range: _ }) => { for alias in names { visitor.visit_alias(alias); } @@ -356,11 +298,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { } Stmt::Global(_) => {} Stmt::Nonlocal(_) => {} - Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => visitor.visit_expr(value), - Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::LineMagic(_) => {} + Stmt::Expr(ast::StmtExpr { value, range: _ }) => visitor.visit_expr(value), + Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {} } } @@ -377,7 +316,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::BoolOp(ast::ExprBoolOp { op, values, - range: _range, + range: _, }) => { visitor.visit_bool_op(op); for expr in values { @@ -387,7 +326,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::NamedExpr(ast::ExprNamedExpr { target, value, - range: _range, + range: _, }) => { visitor.visit_expr(value); visitor.visit_expr(target); @@ -396,7 +335,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { left, op, right, - range: _range, + range: _, }) => { visitor.visit_expr(left); visitor.visit_operator(op); @@ -405,24 +344,26 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::UnaryOp(ast::ExprUnaryOp { op, operand, - range: _range, + range: _, }) => { visitor.visit_unary_op(op); visitor.visit_expr(operand); } Expr::Lambda(ast::ExprLambda { - args, + parameters, body, - range: _range, + range: _, }) => { - visitor.visit_arguments(args); + if let Some(parameters) = parameters { + visitor.visit_parameters(parameters); + } visitor.visit_expr(body); } Expr::IfExp(ast::ExprIfExp { test, body, orelse, - range: _range, + range: _, }) => { visitor.visit_expr(test); visitor.visit_expr(body); @@ -431,7 +372,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::Dict(ast::ExprDict { keys, values, - range: _range, + range: _, }) => { for expr in keys.iter().flatten() { visitor.visit_expr(expr); @@ -440,10 +381,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } } - Expr::Set(ast::ExprSet { - elts, - range: _range, - }) => { + Expr::Set(ast::ExprSet { elts, range: _ }) => { for expr in elts { visitor.visit_expr(expr); } @@ -451,7 +389,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::ListComp(ast::ExprListComp { elt, generators, - range: _range, + range: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); @@ -461,7 +399,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::SetComp(ast::ExprSetComp { elt, generators, - range: _range, + range: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); @@ -472,7 +410,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { key, value, generators, - range: _range, + range: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); @@ -483,34 +421,25 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, - range: _range, + range: _, }) => { for comprehension in generators { visitor.visit_comprehension(comprehension); } visitor.visit_expr(elt); } - Expr::Await(ast::ExprAwait { - value, - range: _range, - }) => visitor.visit_expr(value), - Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => { + Expr::Await(ast::ExprAwait { value, range: _ }) => visitor.visit_expr(value), + Expr::Yield(ast::ExprYield { value, range: _ }) => { if let Some(expr) = value { visitor.visit_expr(expr); } } - Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) => visitor.visit_expr(value), + Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) => visitor.visit_expr(value), Expr::Compare(ast::ExprCompare { left, ops, comparators, - range: _range, + range: _, }) => { visitor.visit_expr(left); for cmp_op in ops { @@ -522,17 +451,11 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { } Expr::Call(ast::ExprCall { func, - args, - keywords, - range: _range, + arguments, + range: _, }) => { visitor.visit_expr(func); - for expr in args { - visitor.visit_expr(expr); - } - for keyword in keywords { - visitor.visit_keyword(keyword); - } + visitor.visit_arguments(arguments); } Expr::FormattedValue(ast::ExprFormattedValue { value, format_spec, .. @@ -542,10 +465,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_format_spec(expr); } } - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { + Expr::FString(ast::ExprFString { values, .. }) => { for expr in values { visitor.visit_expr(expr); } @@ -559,7 +479,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { value, slice, ctx, - range: _range, + range: _, }) => { visitor.visit_expr(value); visitor.visit_expr(slice); @@ -568,7 +488,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::Starred(ast::ExprStarred { value, ctx, - range: _range, + range: _, }) => { visitor.visit_expr(value); visitor.visit_expr_context(ctx); @@ -579,7 +499,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::List(ast::ExprList { elts, ctx, - range: _range, + range: _, }) => { for expr in elts { visitor.visit_expr(expr); @@ -589,7 +509,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { Expr::Tuple(ast::ExprTuple { elts, ctx, - range: _range, + range: _, }) => { for expr in elts { visitor.visit_expr(expr); @@ -600,7 +520,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { lower, upper, step, - range: _range, + range: _, }) => { if let Some(expr) = lower { visitor.visit_expr(expr); @@ -612,7 +532,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } } - Expr::LineMagic(_) => {} + Expr::IpyEscapeCommand(_) => {} } } @@ -646,42 +566,51 @@ pub fn walk_format_spec<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, format_spe } pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) { + for arg in &arguments.args { + visitor.visit_expr(arg); + } + for keyword in &arguments.keywords { + visitor.visit_keyword(keyword); + } +} + +pub fn walk_parameters<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameters: &'a Parameters) { // Defaults are evaluated before annotations. - for arg in &arguments.posonlyargs { + for arg in ¶meters.posonlyargs { if let Some(default) = &arg.default { visitor.visit_expr(default); } } - for arg in &arguments.args { + for arg in ¶meters.args { if let Some(default) = &arg.default { visitor.visit_expr(default); } } - for arg in &arguments.kwonlyargs { + for arg in ¶meters.kwonlyargs { if let Some(default) = &arg.default { visitor.visit_expr(default); } } - for arg in &arguments.posonlyargs { - visitor.visit_arg(&arg.def); + for arg in ¶meters.posonlyargs { + visitor.visit_parameter(&arg.parameter); } - for arg in &arguments.args { - visitor.visit_arg(&arg.def); + for arg in ¶meters.args { + visitor.visit_parameter(&arg.parameter); } - if let Some(arg) = &arguments.vararg { - visitor.visit_arg(arg); + if let Some(arg) = ¶meters.vararg { + visitor.visit_parameter(arg); } - for arg in &arguments.kwonlyargs { - visitor.visit_arg(&arg.def); + for arg in ¶meters.kwonlyargs { + visitor.visit_parameter(&arg.parameter); } - if let Some(arg) = &arguments.kwarg { - visitor.visit_arg(arg); + if let Some(arg) = ¶meters.kwarg { + visitor.visit_parameter(arg); } } -pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) { - if let Some(expr) = &arg.annotation { +pub fn walk_parameter<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameter: &'a Parameter) { + if let Some(expr) = ¶meter.annotation { visitor.visit_annotation(expr); } } @@ -697,6 +626,12 @@ pub fn walk_with_item<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, with_item: & } } +pub fn walk_type_params<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_params: &'a TypeParams) { + for type_param in &type_params.type_params { + visitor.visit_type_param(type_param); + } +} + pub fn walk_type_param<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_param: &'a TypeParam) { match type_param { TypeParam::TypeVar(TypeParamTypeVar { @@ -722,15 +657,11 @@ pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) { match pattern { - Pattern::MatchValue(ast::PatternMatchValue { - value, - range: _range, - }) => visitor.visit_expr(value), + Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => { + visitor.visit_expr(value); + } Pattern::MatchSingleton(_) => {} - Pattern::MatchSequence(ast::PatternMatchSequence { - patterns, - range: _range, - }) => { + Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } @@ -764,10 +695,7 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P visitor.visit_pattern(pattern); } } - Pattern::MatchOr(ast::PatternMatchOr { - patterns, - range: _range, - }) => { + Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => { for pattern in patterns { visitor.visit_pattern(pattern); } @@ -776,23 +704,19 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P } #[allow(unused_variables)] -pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>( - visitor: &mut V, - expr_context: &'a ExprContext, -) { -} +pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(visitor: &V, expr_context: &'a ExprContext) {} #[allow(unused_variables)] -pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, bool_op: &'a BoolOp) {} +pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, bool_op: &'a BoolOp) {} #[allow(unused_variables)] -pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a Operator) {} +pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &V, operator: &'a Operator) {} #[allow(unused_variables)] -pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, unary_op: &'a UnaryOp) {} +pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, unary_op: &'a UnaryOp) {} #[allow(unused_variables)] -pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, cmp_op: &'a CmpOp) {} +pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, cmp_op: &'a CmpOp) {} #[allow(unused_variables)] -pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, alias: &'a Alias) {} +pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &V, alias: &'a Alias) {} diff --git a/crates/ruff_python_ast/src/visitor/preorder.rs b/crates/ruff_python_ast/src/visitor/preorder.rs index 967f312d667c3..dc171765b5f16 100644 --- a/crates/ruff_python_ast/src/visitor/preorder.rs +++ b/crates/ruff_python_ast/src/visitor/preorder.rs @@ -1,101 +1,143 @@ +use crate::node::{AnyNodeRef, AstNode}; use crate::{ - self as ast, Alias, Arg, ArgWithDefault, Arguments, BoolOp, CmpOp, Comprehension, Constant, - Decorator, ElifElseClause, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Pattern, - Stmt, TypeParam, TypeParamTypeVar, UnaryOp, WithItem, + Alias, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, ElifElseClause, + ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Parameter, ParameterWithDefault, + Parameters, Pattern, Stmt, TypeParam, TypeParams, UnaryOp, WithItem, }; /// Visitor that traverses all nodes recursively in pre-order. pub trait PreorderVisitor<'a> { + #[inline] + fn enter_node(&mut self, _node: AnyNodeRef<'a>) -> TraversalSignal { + TraversalSignal::Traverse + } + + #[inline(always)] + fn leave_node(&mut self, _node: AnyNodeRef<'a>) {} + + #[inline] fn visit_mod(&mut self, module: &'a Mod) { walk_module(self, module); } + #[inline] fn visit_stmt(&mut self, stmt: &'a Stmt) { walk_stmt(self, stmt); } + #[inline] fn visit_annotation(&mut self, expr: &'a Expr) { walk_annotation(self, expr); } + #[inline] fn visit_expr(&mut self, expr: &'a Expr) { walk_expr(self, expr); } + #[inline] fn visit_decorator(&mut self, decorator: &'a Decorator) { walk_decorator(self, decorator); } + #[inline] fn visit_constant(&mut self, _constant: &'a Constant) {} + #[inline] fn visit_bool_op(&mut self, bool_op: &'a BoolOp) { walk_bool_op(self, bool_op); } + #[inline] fn visit_operator(&mut self, operator: &'a Operator) { walk_operator(self, operator); } + #[inline] fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) { walk_unary_op(self, unary_op); } + #[inline] fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) { walk_cmp_op(self, cmp_op); } + #[inline] fn visit_comprehension(&mut self, comprehension: &'a Comprehension) { walk_comprehension(self, comprehension); } + #[inline] fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) { walk_except_handler(self, except_handler); } + #[inline] fn visit_format_spec(&mut self, format_spec: &'a Expr) { walk_format_spec(self, format_spec); } + #[inline] fn visit_arguments(&mut self, arguments: &'a Arguments) { walk_arguments(self, arguments); } - fn visit_arg(&mut self, arg: &'a Arg) { - walk_arg(self, arg); + #[inline] + fn visit_parameters(&mut self, parameters: &'a Parameters) { + walk_parameters(self, parameters); + } + + #[inline] + fn visit_parameter(&mut self, arg: &'a Parameter) { + walk_parameter(self, arg); } - fn visit_arg_with_default(&mut self, arg_with_default: &'a ArgWithDefault) { - walk_arg_with_default(self, arg_with_default); + fn visit_parameter_with_default(&mut self, parameter_with_default: &'a ParameterWithDefault) { + walk_parameter_with_default(self, parameter_with_default); } + #[inline] fn visit_keyword(&mut self, keyword: &'a Keyword) { walk_keyword(self, keyword); } + #[inline] fn visit_alias(&mut self, alias: &'a Alias) { walk_alias(self, alias); } + #[inline] fn visit_with_item(&mut self, with_item: &'a WithItem) { walk_with_item(self, with_item); } + #[inline] + fn visit_type_params(&mut self, type_params: &'a TypeParams) { + walk_type_params(self, type_params); + } + + #[inline] fn visit_type_param(&mut self, type_param: &'a TypeParam) { walk_type_param(self, type_param); } + #[inline] fn visit_match_case(&mut self, match_case: &'a MatchCase) { walk_match_case(self, match_case); } + #[inline] fn visit_pattern(&mut self, pattern: &'a Pattern) { walk_pattern(self, pattern); } + #[inline] fn visit_body(&mut self, body: &'a [Stmt]) { walk_body(self, body); } + #[inline] fn visit_elif_else_clause(&mut self, elif_else_clause: &'a ElifElseClause) { walk_elif_else_clause(self, elif_else_clause); } @@ -105,12 +147,15 @@ pub fn walk_module<'a, V>(visitor: &mut V, module: &'a Mod) where V: PreorderVisitor<'a> + ?Sized, { - match module { - Mod::Module(ast::ModModule { body, range: _ }) => { - visitor.visit_body(body); + let node = AnyNodeRef::from(module); + if visitor.enter_node(node).is_traverse() { + match module { + Mod::Module(module) => module.visit_preorder(visitor), + Mod::Expression(module) => module.visit_preorder(visitor), } - Mod::Expression(ast::ModExpression { body, range: _ }) => visitor.visit_expr(body), } + + visitor.leave_node(node); } pub fn walk_body<'a, V>(visitor: &mut V, body: &'a [Stmt]) @@ -126,667 +171,212 @@ pub fn walk_stmt<'a, V>(visitor: &mut V, stmt: &'a Stmt) where V: PreorderVisitor<'a> + ?Sized, { - match stmt { - Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => visitor.visit_expr(value), - - Stmt::FunctionDef(ast::StmtFunctionDef { - args, - body, - decorator_list, - returns, - type_params, - .. - }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - args, - body, - decorator_list, - returns, - type_params, - .. - }) => { - for decorator in decorator_list { - visitor.visit_decorator(decorator); - } - - for type_param in type_params { - visitor.visit_type_param(type_param); - } - - visitor.visit_arguments(args); - - for expr in returns { - visitor.visit_annotation(expr); - } - - visitor.visit_body(body); - } - - Stmt::ClassDef(ast::StmtClassDef { - bases, - keywords, - body, - decorator_list, - type_params, - .. - }) => { - for decorator in decorator_list { - visitor.visit_decorator(decorator); - } - - for type_param in type_params { - visitor.visit_type_param(type_param); - } - - for expr in bases { - visitor.visit_expr(expr); - } - - for keyword in keywords { - visitor.visit_keyword(keyword); - } - - visitor.visit_body(body); - } - - Stmt::Return(ast::StmtReturn { - value, - range: _range, - }) => { - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Stmt::Delete(ast::StmtDelete { - targets, - range: _range, - }) => { - for expr in targets { - visitor.visit_expr(expr); - } - } - - Stmt::TypeAlias(ast::StmtTypeAlias { - range: _range, - name, - type_params, - value, - }) => { - visitor.visit_expr(name); - for type_param in type_params { - visitor.visit_type_param(type_param); - } - visitor.visit_expr(value); - } - - Stmt::Assign(ast::StmtAssign { - targets, - value, - range: _, - }) => { - for expr in targets { - visitor.visit_expr(expr); - } - - visitor.visit_expr(value); - } - - Stmt::AugAssign(ast::StmtAugAssign { - target, - op, - value, - range: _range, - }) => { - visitor.visit_expr(target); - visitor.visit_operator(op); - visitor.visit_expr(value); - } - - Stmt::AnnAssign(ast::StmtAnnAssign { - target, - annotation, - value, - range: _, - simple: _, - }) => { - visitor.visit_expr(target); - visitor.visit_annotation(annotation); - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Stmt::For(ast::StmtFor { - target, - iter, - body, - orelse, - .. - }) - | Stmt::AsyncFor(ast::StmtAsyncFor { - target, - iter, - body, - orelse, - .. - }) => { - visitor.visit_expr(target); - visitor.visit_expr(iter); - visitor.visit_body(body); - visitor.visit_body(orelse); - } - - Stmt::While(ast::StmtWhile { - test, - body, - orelse, - range: _range, - }) => { - visitor.visit_expr(test); - visitor.visit_body(body); - visitor.visit_body(orelse); - } - - Stmt::If(ast::StmtIf { - test, - body, - elif_else_clauses, - range: _range, - }) => { - visitor.visit_expr(test); - visitor.visit_body(body); - for clause in elif_else_clauses { - visitor.visit_elif_else_clause(clause); - } - } - - Stmt::With(ast::StmtWith { - items, - body, - range: _, - }) - | Stmt::AsyncWith(ast::StmtAsyncWith { - items, - body, - range: _, - }) => { - for with_item in items { - visitor.visit_with_item(with_item); - } - visitor.visit_body(body); - } - - Stmt::Match(ast::StmtMatch { - subject, - cases, - range: _range, - }) => { - visitor.visit_expr(subject); - for match_case in cases { - visitor.visit_match_case(match_case); - } - } - - Stmt::Raise(ast::StmtRaise { - exc, - cause, - range: _range, - }) => { - if let Some(expr) = exc { - visitor.visit_expr(expr); - }; - if let Some(expr) = cause { - visitor.visit_expr(expr); - }; - } - - Stmt::Try(ast::StmtTry { - body, - handlers, - orelse, - finalbody, - range: _range, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, - }) => { - visitor.visit_body(body); - for except_handler in handlers { - visitor.visit_except_handler(except_handler); - } - visitor.visit_body(orelse); - visitor.visit_body(finalbody); - } - - Stmt::Assert(ast::StmtAssert { - test, - msg, - range: _range, - }) => { - visitor.visit_expr(test); - if let Some(expr) = msg { - visitor.visit_expr(expr); - } - } - - Stmt::Import(ast::StmtImport { - names, - range: _range, - }) => { - for alias in names { - visitor.visit_alias(alias); - } - } + let node = AnyNodeRef::from(stmt); + + if visitor.enter_node(node).is_traverse() { + match stmt { + Stmt::Expr(stmt) => stmt.visit_preorder(visitor), + Stmt::FunctionDef(stmt) => stmt.visit_preorder(visitor), + Stmt::ClassDef(stmt) => stmt.visit_preorder(visitor), + Stmt::Return(stmt) => stmt.visit_preorder(visitor), + Stmt::Delete(stmt) => stmt.visit_preorder(visitor), + Stmt::TypeAlias(stmt) => stmt.visit_preorder(visitor), + Stmt::Assign(stmt) => stmt.visit_preorder(visitor), + Stmt::AugAssign(stmt) => stmt.visit_preorder(visitor), + Stmt::AnnAssign(stmt) => stmt.visit_preorder(visitor), + Stmt::For(stmt) => stmt.visit_preorder(visitor), + Stmt::While(stmt) => stmt.visit_preorder(visitor), + Stmt::If(stmt) => stmt.visit_preorder(visitor), + Stmt::With(stmt) => stmt.visit_preorder(visitor), + Stmt::Match(stmt) => stmt.visit_preorder(visitor), + Stmt::Raise(stmt) => stmt.visit_preorder(visitor), + Stmt::Try(stmt) => stmt.visit_preorder(visitor), + Stmt::Assert(stmt) => stmt.visit_preorder(visitor), + Stmt::Import(stmt) => stmt.visit_preorder(visitor), + Stmt::ImportFrom(stmt) => stmt.visit_preorder(visitor), + Stmt::Pass(stmt) => stmt.visit_preorder(visitor), + Stmt::Break(stmt) => stmt.visit_preorder(visitor), + Stmt::Continue(stmt) => stmt.visit_preorder(visitor), + Stmt::Global(stmt) => stmt.visit_preorder(visitor), + Stmt::Nonlocal(stmt) => stmt.visit_preorder(visitor), + Stmt::IpyEscapeCommand(stmt) => stmt.visit_preorder(visitor), + } + } + + visitor.leave_node(node); +} - Stmt::ImportFrom(ast::StmtImportFrom { - range: _, - module: _, - names, - level: _, - }) => { - for alias in names { - visitor.visit_alias(alias); - } - } +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum TraversalSignal { + Traverse, + Skip, +} - Stmt::Pass(_) - | Stmt::Break(_) - | Stmt::Continue(_) - | Stmt::Global(_) - | Stmt::Nonlocal(_) - | Stmt::LineMagic(_) => {} +impl TraversalSignal { + const fn is_traverse(self) -> bool { + matches!(self, TraversalSignal::Traverse) } } pub fn walk_annotation<'a, V: PreorderVisitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { - visitor.visit_expr(expr); + let node = AnyNodeRef::from(expr); + if visitor.enter_node(node).is_traverse() { + visitor.visit_expr(expr); + } + + visitor.leave_node(node); } pub fn walk_decorator<'a, V>(visitor: &mut V, decorator: &'a Decorator) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_expr(&decorator.expression); + let node = AnyNodeRef::from(decorator); + if visitor.enter_node(node).is_traverse() { + decorator.visit_preorder(visitor); + } + + visitor.leave_node(node); } pub fn walk_expr<'a, V>(visitor: &mut V, expr: &'a Expr) where V: PreorderVisitor<'a> + ?Sized, { - match expr { - Expr::BoolOp(ast::ExprBoolOp { - op, - values, - range: _range, - }) => match values.as_slice() { - [left, rest @ ..] => { - visitor.visit_expr(left); - visitor.visit_bool_op(op); - for expr in rest { - visitor.visit_expr(expr); - } - } - [] => { - visitor.visit_bool_op(op); - } - }, - - Expr::NamedExpr(ast::ExprNamedExpr { - target, - value, - range: _range, - }) => { - visitor.visit_expr(target); - visitor.visit_expr(value); - } - - Expr::BinOp(ast::ExprBinOp { - left, - op, - right, - range: _range, - }) => { - visitor.visit_expr(left); - visitor.visit_operator(op); - visitor.visit_expr(right); - } - - Expr::UnaryOp(ast::ExprUnaryOp { - op, - operand, - range: _range, - }) => { - visitor.visit_unary_op(op); - visitor.visit_expr(operand); - } - - Expr::Lambda(ast::ExprLambda { - args, - body, - range: _range, - }) => { - visitor.visit_arguments(args); - visitor.visit_expr(body); - } - - Expr::IfExp(ast::ExprIfExp { - test, - body, - orelse, - range: _range, - }) => { - // `body if test else orelse` - visitor.visit_expr(body); - visitor.visit_expr(test); - visitor.visit_expr(orelse); - } - - Expr::Dict(ast::ExprDict { - keys, - values, - range: _range, - }) => { - for (key, value) in keys.iter().zip(values) { - if let Some(key) = key { - visitor.visit_expr(key); - } - visitor.visit_expr(value); - } - } - - Expr::Set(ast::ExprSet { - elts, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::ListComp(ast::ExprListComp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::SetComp(ast::ExprSetComp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::DictComp(ast::ExprDictComp { - key, - value, - generators, - range: _range, - }) => { - visitor.visit_expr(key); - visitor.visit_expr(value); - - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::GeneratorExp(ast::ExprGeneratorExp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::Await(ast::ExprAwait { - value, - range: _range, - }) - | Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) => visitor.visit_expr(value), - - Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => { - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Expr::Compare(ast::ExprCompare { - left, - ops, - comparators, - range: _range, - }) => { - visitor.visit_expr(left); - - for (op, comparator) in ops.iter().zip(comparators) { - visitor.visit_cmp_op(op); - visitor.visit_expr(comparator); - } - } - - Expr::Call(ast::ExprCall { - func, - args, - keywords, - range: _range, - }) => { - visitor.visit_expr(func); - for expr in args { - visitor.visit_expr(expr); - } - for keyword in keywords { - visitor.visit_keyword(keyword); - } - } - - Expr::FormattedValue(ast::ExprFormattedValue { - value, format_spec, .. - }) => { - visitor.visit_expr(value); - - if let Some(expr) = format_spec { - visitor.visit_format_spec(expr); - } - } - - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { - for expr in values { - visitor.visit_expr(expr); - } - } - - Expr::Constant(ast::ExprConstant { - value, - range: _, - kind: _, - }) => visitor.visit_constant(value), - - Expr::Attribute(ast::ExprAttribute { - value, - attr: _, - ctx: _, - range: _, - }) => { - visitor.visit_expr(value); - } - - Expr::Subscript(ast::ExprSubscript { - value, - slice, - ctx: _, - range: _range, - }) => { - visitor.visit_expr(value); - visitor.visit_expr(slice); - } - Expr::Starred(ast::ExprStarred { - value, - ctx: _, - range: _range, - }) => { - visitor.visit_expr(value); - } - - Expr::Name(ast::ExprName { - id: _, - ctx: _, - range: _, - }) => {} - - Expr::List(ast::ExprList { - elts, - ctx: _, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - Expr::Tuple(ast::ExprTuple { - elts, - ctx: _, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::Slice(ast::ExprSlice { - lower, - upper, - step, - range: _range, - }) => { - if let Some(expr) = lower { - visitor.visit_expr(expr); - } - if let Some(expr) = upper { - visitor.visit_expr(expr); - } - if let Some(expr) = step { - visitor.visit_expr(expr); - } - } - Expr::LineMagic(_) => (), - } + let node = AnyNodeRef::from(expr); + if visitor.enter_node(node).is_traverse() { + match expr { + Expr::BoolOp(expr) => expr.visit_preorder(visitor), + Expr::NamedExpr(expr) => expr.visit_preorder(visitor), + Expr::BinOp(expr) => expr.visit_preorder(visitor), + Expr::UnaryOp(expr) => expr.visit_preorder(visitor), + Expr::Lambda(expr) => expr.visit_preorder(visitor), + Expr::IfExp(expr) => expr.visit_preorder(visitor), + Expr::Dict(expr) => expr.visit_preorder(visitor), + Expr::Set(expr) => expr.visit_preorder(visitor), + Expr::ListComp(expr) => expr.visit_preorder(visitor), + Expr::SetComp(expr) => expr.visit_preorder(visitor), + Expr::DictComp(expr) => expr.visit_preorder(visitor), + Expr::GeneratorExp(expr) => expr.visit_preorder(visitor), + Expr::Await(expr) => expr.visit_preorder(visitor), + Expr::Yield(expr) => expr.visit_preorder(visitor), + Expr::YieldFrom(expr) => expr.visit_preorder(visitor), + Expr::Compare(expr) => expr.visit_preorder(visitor), + Expr::Call(expr) => expr.visit_preorder(visitor), + Expr::FormattedValue(expr) => expr.visit_preorder(visitor), + Expr::FString(expr) => expr.visit_preorder(visitor), + Expr::Constant(expr) => expr.visit_preorder(visitor), + Expr::Attribute(expr) => expr.visit_preorder(visitor), + Expr::Subscript(expr) => expr.visit_preorder(visitor), + Expr::Starred(expr) => expr.visit_preorder(visitor), + Expr::Name(expr) => expr.visit_preorder(visitor), + Expr::List(expr) => expr.visit_preorder(visitor), + Expr::Tuple(expr) => expr.visit_preorder(visitor), + Expr::Slice(expr) => expr.visit_preorder(visitor), + Expr::IpyEscapeCommand(expr) => expr.visit_preorder(visitor), + } + } + + visitor.leave_node(node); } pub fn walk_comprehension<'a, V>(visitor: &mut V, comprehension: &'a Comprehension) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_expr(&comprehension.target); - visitor.visit_expr(&comprehension.iter); - - for expr in &comprehension.ifs { - visitor.visit_expr(expr); + let node = AnyNodeRef::from(comprehension); + if visitor.enter_node(node).is_traverse() { + comprehension.visit_preorder(visitor); } + + visitor.leave_node(node); } pub fn walk_elif_else_clause<'a, V>(visitor: &mut V, elif_else_clause: &'a ElifElseClause) where V: PreorderVisitor<'a> + ?Sized, { - if let Some(test) = &elif_else_clause.test { - visitor.visit_expr(test); + let node = AnyNodeRef::from(elif_else_clause); + if visitor.enter_node(node).is_traverse() { + elif_else_clause.visit_preorder(visitor); } - visitor.visit_body(&elif_else_clause.body); + + visitor.leave_node(node); } pub fn walk_except_handler<'a, V>(visitor: &mut V, except_handler: &'a ExceptHandler) where V: PreorderVisitor<'a> + ?Sized, { - match except_handler { - ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { - range: _, - type_, - name: _, - body, - }) => { - if let Some(expr) = type_ { - visitor.visit_expr(expr); - } - visitor.visit_body(body); + let node = AnyNodeRef::from(except_handler); + if visitor.enter_node(node).is_traverse() { + match except_handler { + ExceptHandler::ExceptHandler(except_handler) => except_handler.visit_preorder(visitor), } } + visitor.leave_node(node); } pub fn walk_format_spec<'a, V: PreorderVisitor<'a> + ?Sized>( visitor: &mut V, format_spec: &'a Expr, ) { - visitor.visit_expr(format_spec); + let node = AnyNodeRef::from(format_spec); + if visitor.enter_node(node).is_traverse() { + visitor.visit_expr(format_spec); + } + + visitor.leave_node(node); } pub fn walk_arguments<'a, V>(visitor: &mut V, arguments: &'a Arguments) where V: PreorderVisitor<'a> + ?Sized, { - for arg in arguments.posonlyargs.iter().chain(&arguments.args) { - visitor.visit_arg_with_default(arg); + let node = AnyNodeRef::from(arguments); + if visitor.enter_node(node).is_traverse() { + arguments.visit_preorder(visitor); } - if let Some(arg) = &arguments.vararg { - visitor.visit_arg(arg); - } + visitor.leave_node(node); +} - for arg in &arguments.kwonlyargs { - visitor.visit_arg_with_default(arg); +pub fn walk_parameters<'a, V>(visitor: &mut V, parameters: &'a Parameters) +where + V: PreorderVisitor<'a> + ?Sized, +{ + let node = AnyNodeRef::from(parameters); + if visitor.enter_node(node).is_traverse() { + parameters.visit_preorder(visitor); } - if let Some(arg) = &arguments.kwarg { - visitor.visit_arg(arg); - } + visitor.leave_node(node); } -pub fn walk_arg<'a, V>(visitor: &mut V, arg: &'a Arg) +pub fn walk_parameter<'a, V>(visitor: &mut V, parameter: &'a Parameter) where V: PreorderVisitor<'a> + ?Sized, { - if let Some(expr) = &arg.annotation { - visitor.visit_annotation(expr); + let node = AnyNodeRef::from(parameter); + + if visitor.enter_node(node).is_traverse() { + parameter.visit_preorder(visitor); } + visitor.leave_node(node); } -pub fn walk_arg_with_default<'a, V>(visitor: &mut V, arg_with_default: &'a ArgWithDefault) -where +pub fn walk_parameter_with_default<'a, V>( + visitor: &mut V, + parameter_with_default: &'a ParameterWithDefault, +) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_arg(&arg_with_default.def); - if let Some(expr) = &arg_with_default.default { - visitor.visit_expr(expr); + let node = AnyNodeRef::from(parameter_with_default); + if visitor.enter_node(node).is_traverse() { + parameter_with_default.visit_preorder(visitor); } + + visitor.leave_node(node); } #[inline] @@ -794,125 +384,80 @@ pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_expr(&keyword.value); + let node = AnyNodeRef::from(keyword); + + if visitor.enter_node(node).is_traverse() { + keyword.visit_preorder(visitor); + } + visitor.leave_node(node); } pub fn walk_with_item<'a, V>(visitor: &mut V, with_item: &'a WithItem) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_expr(&with_item.context_expr); + let node = AnyNodeRef::from(with_item); + if visitor.enter_node(node).is_traverse() { + with_item.visit_preorder(visitor); + } + visitor.leave_node(node); +} - if let Some(expr) = &with_item.optional_vars { - visitor.visit_expr(expr); +pub fn walk_type_params<'a, V>(visitor: &mut V, type_params: &'a TypeParams) +where + V: PreorderVisitor<'a> + ?Sized, +{ + let node = AnyNodeRef::from(type_params); + if visitor.enter_node(node).is_traverse() { + type_params.visit_preorder(visitor); } + visitor.leave_node(node); } pub fn walk_type_param<'a, V>(visitor: &mut V, type_param: &'a TypeParam) where V: PreorderVisitor<'a> + ?Sized, { - match type_param { - TypeParam::TypeVar(TypeParamTypeVar { - bound, - name: _, - range: _, - }) => { - if let Some(expr) = bound { - visitor.visit_expr(expr); - } + let node = AnyNodeRef::from(type_param); + if visitor.enter_node(node).is_traverse() { + match type_param { + TypeParam::TypeVar(type_param) => type_param.visit_preorder(visitor), + TypeParam::TypeVarTuple(type_param) => type_param.visit_preorder(visitor), + TypeParam::ParamSpec(type_param) => type_param.visit_preorder(visitor), } - TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {} } + visitor.leave_node(node); } pub fn walk_match_case<'a, V>(visitor: &mut V, match_case: &'a MatchCase) where V: PreorderVisitor<'a> + ?Sized, { - visitor.visit_pattern(&match_case.pattern); - if let Some(expr) = &match_case.guard { - visitor.visit_expr(expr); + let node = AnyNodeRef::from(match_case); + if visitor.enter_node(node).is_traverse() { + match_case.visit_preorder(visitor); } - visitor.visit_body(&match_case.body); + visitor.leave_node(node); } pub fn walk_pattern<'a, V>(visitor: &mut V, pattern: &'a Pattern) where V: PreorderVisitor<'a> + ?Sized, { - match pattern { - Pattern::MatchValue(ast::PatternMatchValue { - value, - range: _range, - }) => visitor.visit_expr(value), - - Pattern::MatchSingleton(ast::PatternMatchSingleton { - value, - range: _range, - }) => { - visitor.visit_constant(value); - } - - Pattern::MatchSequence(ast::PatternMatchSequence { - patterns, - range: _range, - }) => { - for pattern in patterns { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchMapping(ast::PatternMatchMapping { - keys, - patterns, - range: _, - rest: _, - }) => { - for (key, pattern) in keys.iter().zip(patterns) { - visitor.visit_expr(key); - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchClass(ast::PatternMatchClass { - cls, - patterns, - kwd_attrs: _, - kwd_patterns, - range: _, - }) => { - visitor.visit_expr(cls); - for pattern in patterns { - visitor.visit_pattern(pattern); - } - - for pattern in kwd_patterns { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchStar(_) => {} - - Pattern::MatchAs(ast::PatternMatchAs { - pattern, - range: _, - name: _, - }) => { - if let Some(pattern) = pattern { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchOr(ast::PatternMatchOr { - patterns, - range: _range, - }) => { - for pattern in patterns { - visitor.visit_pattern(pattern); - } - } - } + let node = AnyNodeRef::from(pattern); + if visitor.enter_node(node).is_traverse() { + match pattern { + Pattern::MatchValue(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchSingleton(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchSequence(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchMapping(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchClass(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchStar(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchAs(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchOr(pattern) => pattern.visit_preorder(visitor), + } + } + visitor.leave_node(node); } pub fn walk_bool_op<'a, V>(_visitor: &mut V, _bool_op: &'a BoolOp) @@ -943,8 +488,13 @@ where } #[inline] -pub fn walk_alias<'a, V>(_visitor: &mut V, _alias: &'a Alias) +pub fn walk_alias<'a, V>(visitor: &mut V, alias: &'a Alias) where V: PreorderVisitor<'a> + ?Sized, { + let node = AnyNodeRef::from(alias); + if visitor.enter_node(node).is_traverse() { + alias.visit_preorder(visitor); + } + visitor.leave_node(node); } diff --git a/crates/ruff_python_ast/src/whitespace.rs b/crates/ruff_python_ast/src/whitespace.rs index 282076ee29781..6f89365efb6da 100644 --- a/crates/ruff_python_ast/src/whitespace.rs +++ b/crates/ruff_python_ast/src/whitespace.rs @@ -1,10 +1,8 @@ -use crate::{Ranged, Stmt}; +use ruff_python_trivia::{indentation_at_offset, is_python_whitespace, PythonWhitespace}; +use ruff_source_file::{newlines::UniversalNewlineIterator, Locator}; use ruff_text_size::{TextRange, TextSize}; -use ruff_python_trivia::{ - has_trailing_content, indentation_at_offset, is_python_whitespace, PythonWhitespace, -}; -use ruff_source_file::{newlines::UniversalNewlineIterator, Locator}; +use crate::{Ranged, Stmt}; /// Extract the leading indentation from a line. #[inline] @@ -18,20 +16,12 @@ where /// Return the end offset at which the empty lines following a statement. pub fn trailing_lines_end(stmt: &Stmt, locator: &Locator) -> TextSize { let line_end = locator.full_line_end(stmt.end()); - let rest = &locator.contents()[usize::from(line_end)..]; - - UniversalNewlineIterator::with_offset(rest, line_end) + UniversalNewlineIterator::with_offset(locator.after(line_end), line_end) .take_while(|line| line.trim_whitespace().is_empty()) .last() .map_or(line_end, |line| line.full_end()) } -/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with -/// other statements following it. -pub fn followed_by_multi_statement_line(stmt: &Stmt, locator: &Locator) -> bool { - has_trailing_content(stmt.end(), locator) -} - /// If a [`Ranged`] has a trailing comment, return the index of the hash. pub fn trailing_comment_start_offset(located: &T, locator: &Locator) -> Option where @@ -39,7 +29,7 @@ where { let line_end = locator.line_end(located.end()); - let trailing = &locator.contents()[TextRange::new(located.end(), line_end)]; + let trailing = locator.slice(TextRange::new(located.end(), line_end)); for (index, char) in trailing.char_indices() { if char == '#' { diff --git a/crates/ruff_python_ast/tests/identifier.rs b/crates/ruff_python_ast/tests/identifier.rs index cf24c84d004cc..a32dd12c26d82 100644 --- a/crates/ruff_python_ast/tests/identifier.rs +++ b/crates/ruff_python_ast/tests/identifier.rs @@ -1,5 +1,4 @@ -use ruff_python_ast::Stmt; -use ruff_python_parser::{Parse, ParseError}; +use ruff_python_parser::{parse_suite, ParseError}; use ruff_text_size::{TextRange, TextSize}; use ruff_python_ast::identifier; @@ -13,8 +12,9 @@ else: pass "# .trim(); - let stmt = Stmt::parse(contents, "")?; - let range = identifier::else_(&stmt, contents).unwrap(); + let stmts = parse_suite(contents, "")?; + let stmt = stmts.first().unwrap(); + let range = identifier::else_(stmt, contents).unwrap(); assert_eq!(&contents[range], "else"); assert_eq!( range, diff --git a/crates/ruff_python_ast/tests/parenthesize.rs b/crates/ruff_python_ast/tests/parenthesize.rs new file mode 100644 index 0000000000000..9713e7b7ddad9 --- /dev/null +++ b/crates/ruff_python_ast/tests/parenthesize.rs @@ -0,0 +1,102 @@ +use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_parser::parse_expression; +use ruff_text_size::TextRange; + +#[test] +fn test_parenthesized_name() { + let source_code = r#"(x) + 1"#; + let expr = parse_expression(source_code, "").unwrap(); + + let bin_op = expr.as_bin_op_expr().unwrap(); + let name = bin_op.left.as_ref(); + + let parenthesized = parenthesized_range(name.into(), bin_op.into(), source_code); + assert_eq!(parenthesized, Some(TextRange::new(0.into(), 3.into()))); +} + +#[test] +fn test_non_parenthesized_name() { + let source_code = r#"x + 1"#; + let expr = parse_expression(source_code, "").unwrap(); + + let bin_op = expr.as_bin_op_expr().unwrap(); + let name = bin_op.left.as_ref(); + + let parenthesized = parenthesized_range(name.into(), bin_op.into(), source_code); + assert_eq!(parenthesized, None); +} + +#[test] +fn test_parenthesized_argument() { + let source_code = r#"f((a))"#; + let expr = parse_expression(source_code, "").unwrap(); + + let call = expr.as_call_expr().unwrap(); + let arguments = &call.arguments; + let argument = arguments.args.first().unwrap(); + + let parenthesized = parenthesized_range(argument.into(), arguments.into(), source_code); + assert_eq!(parenthesized, Some(TextRange::new(2.into(), 5.into()))); +} + +#[test] +fn test_non_parenthesized_argument() { + let source_code = r#"f(a)"#; + let expr = parse_expression(source_code, "").unwrap(); + + let call = expr.as_call_expr().unwrap(); + let arguments = &call.arguments; + let argument = arguments.args.first().unwrap(); + + let parenthesized = parenthesized_range(argument.into(), arguments.into(), source_code); + assert_eq!(parenthesized, None); +} + +#[test] +fn test_parenthesized_tuple_member() { + let source_code = r#"(a, (b))"#; + let expr = parse_expression(source_code, "").unwrap(); + + let tuple = expr.as_tuple_expr().unwrap(); + let member = tuple.elts.last().unwrap(); + + let parenthesized = parenthesized_range(member.into(), tuple.into(), source_code); + assert_eq!(parenthesized, Some(TextRange::new(4.into(), 7.into()))); +} + +#[test] +fn test_non_parenthesized_tuple_member() { + let source_code = r#"(a, b)"#; + let expr = parse_expression(source_code, "").unwrap(); + + let tuple = expr.as_tuple_expr().unwrap(); + let member = tuple.elts.last().unwrap(); + + let parenthesized = parenthesized_range(member.into(), tuple.into(), source_code); + assert_eq!(parenthesized, None); +} + +#[test] +fn test_twice_parenthesized_name() { + let source_code = r#"((x)) + 1"#; + let expr = parse_expression(source_code, "").unwrap(); + + let bin_op = expr.as_bin_op_expr().unwrap(); + let name = bin_op.left.as_ref(); + + let parenthesized = parenthesized_range(name.into(), bin_op.into(), source_code); + assert_eq!(parenthesized, Some(TextRange::new(0.into(), 5.into()))); +} + +#[test] +fn test_twice_parenthesized_argument() { + let source_code = r#"f(((a + 1)))"#; + let expr = parse_expression(source_code, "").unwrap(); + + let call = expr.as_call_expr().unwrap(); + let arguments = &call.arguments; + let argument = arguments.args.first().unwrap(); + + let parenthesized = parenthesized_range(argument.into(), arguments.into(), source_code); + assert_eq!(parenthesized, Some(TextRange::new(2.into(), 11.into()))); +} diff --git a/crates/ruff_python_ast/tests/preorder.rs b/crates/ruff_python_ast/tests/preorder.rs index a2bc08c42cd1a..8c6cba2f30250 100644 --- a/crates/ruff_python_ast/tests/preorder.rs +++ b/crates/ruff_python_ast/tests/preorder.rs @@ -4,13 +4,13 @@ use insta::assert_snapshot; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::preorder::{ - walk_alias, walk_arg, walk_arguments, walk_comprehension, walk_except_handler, walk_expr, - walk_keyword, walk_match_case, walk_module, walk_pattern, walk_stmt, walk_type_param, + walk_alias, walk_comprehension, walk_except_handler, walk_expr, walk_keyword, walk_match_case, + walk_module, walk_parameter, walk_parameters, walk_pattern, walk_stmt, walk_type_param, walk_with_item, PreorderVisitor, }; use ruff_python_ast::{ - Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, ExceptHandler, Expr, Keyword, - MatchCase, Mod, Operator, Pattern, Stmt, TypeParam, UnaryOp, WithItem, + Alias, BoolOp, CmpOp, Comprehension, Constant, ExceptHandler, Expr, Keyword, MatchCase, Mod, + Operator, Parameter, Parameters, Pattern, Stmt, TypeParam, UnaryOp, WithItem, }; use ruff_python_parser::lexer::lex; use ruff_python_parser::{parse_tokens, Mode}; @@ -231,15 +231,15 @@ impl PreorderVisitor<'_> for RecordVisitor { self.exit_node(); } - fn visit_arguments(&mut self, arguments: &Arguments) { - self.enter_node(arguments); - walk_arguments(self, arguments); + fn visit_parameters(&mut self, parameters: &Parameters) { + self.enter_node(parameters); + walk_parameters(self, parameters); self.exit_node(); } - fn visit_arg(&mut self, arg: &Arg) { - self.enter_node(arg); - walk_arg(self, arg); + fn visit_parameter(&mut self, parameter: &Parameter) { + self.enter_node(parameter); + walk_parameter(self, parameter); self.exit_node(); } diff --git a/crates/ruff_python_ast/tests/snapshots/preorder__decorators.snap b/crates/ruff_python_ast/tests/snapshots/preorder__decorators.snap index fbecff6cd23a5..ff57b138dec47 100644 --- a/crates/ruff_python_ast/tests/snapshots/preorder__decorators.snap +++ b/crates/ruff_python_ast/tests/snapshots/preorder__decorators.snap @@ -5,7 +5,7 @@ expression: trace - ModModule - StmtFunctionDef - ExprName - - Arguments + - Parameters - StmtPass - StmtClassDef - ExprName diff --git a/crates/ruff_python_ast/tests/snapshots/preorder__function_arguments.snap b/crates/ruff_python_ast/tests/snapshots/preorder__function_arguments.snap index c41f0885a7536..68d8454d1d815 100644 --- a/crates/ruff_python_ast/tests/snapshots/preorder__function_arguments.snap +++ b/crates/ruff_python_ast/tests/snapshots/preorder__function_arguments.snap @@ -4,20 +4,20 @@ expression: trace --- - ModModule - StmtFunctionDef - - Arguments - - Arg - - Arg - - Arg - - Arg + - Parameters + - Parameter + - Parameter + - Parameter + - Parameter - ExprConstant - Int(20) - - Arg - - Arg + - Parameter + - Parameter - ExprConstant - Int(5) - - Arg + - Parameter - ExprConstant - Int(20) - - Arg + - Parameter - StmtPass diff --git a/crates/ruff_python_ast/tests/snapshots/preorder__function_positional_only_with_default.snap b/crates/ruff_python_ast/tests/snapshots/preorder__function_positional_only_with_default.snap index c22624ef9dad6..2c9ace59af277 100644 --- a/crates/ruff_python_ast/tests/snapshots/preorder__function_positional_only_with_default.snap +++ b/crates/ruff_python_ast/tests/snapshots/preorder__function_positional_only_with_default.snap @@ -4,14 +4,14 @@ expression: trace --- - ModModule - StmtFunctionDef - - Arguments - - Arg - - Arg + - Parameters + - Parameter + - Parameter - ExprConstant - Int(34) - - Arg + - Parameter - ExprConstant - Int(20) - - Arg + - Parameter - StmtPass diff --git a/crates/ruff_python_ast/tests/snapshots/preorder__function_type_parameters.snap b/crates/ruff_python_ast/tests/snapshots/preorder__function_type_parameters.snap index 06ef9c26247a3..c221faf0490dc 100644 --- a/crates/ruff_python_ast/tests/snapshots/preorder__function_type_parameters.snap +++ b/crates/ruff_python_ast/tests/snapshots/preorder__function_type_parameters.snap @@ -9,7 +9,7 @@ expression: trace - TypeParamTypeVar - TypeParamTypeVarTuple - TypeParamParamSpec - - Arguments + - Parameters - StmtExpr - ExprConstant - Ellipsis diff --git a/crates/ruff_python_ast/tests/snapshots/visitor__decorators.snap b/crates/ruff_python_ast/tests/snapshots/visitor__decorators.snap index 76fe2a083e4e3..c633132e04b4d 100644 --- a/crates/ruff_python_ast/tests/snapshots/visitor__decorators.snap +++ b/crates/ruff_python_ast/tests/snapshots/visitor__decorators.snap @@ -4,7 +4,7 @@ expression: trace --- - StmtFunctionDef - ExprName - - Arguments + - Parameters - StmtPass - StmtClassDef - ExprName diff --git a/crates/ruff_python_ast/tests/snapshots/visitor__function_arguments.snap b/crates/ruff_python_ast/tests/snapshots/visitor__function_arguments.snap index a7c301547628d..aaab46e7dada4 100644 --- a/crates/ruff_python_ast/tests/snapshots/visitor__function_arguments.snap +++ b/crates/ruff_python_ast/tests/snapshots/visitor__function_arguments.snap @@ -3,17 +3,17 @@ source: crates/ruff_python_ast/tests/visitor.rs expression: trace --- - StmtFunctionDef - - Arguments + - Parameters - ExprConstant - ExprConstant - ExprConstant - - Arg - - Arg - - Arg - - Arg - - Arg - - Arg - - Arg - - Arg + - Parameter + - Parameter + - Parameter + - Parameter + - Parameter + - Parameter + - Parameter + - Parameter - StmtPass diff --git a/crates/ruff_python_ast/tests/snapshots/visitor__function_positional_only_with_default.snap b/crates/ruff_python_ast/tests/snapshots/visitor__function_positional_only_with_default.snap index 98a729f3627e9..a53646e2076f6 100644 --- a/crates/ruff_python_ast/tests/snapshots/visitor__function_positional_only_with_default.snap +++ b/crates/ruff_python_ast/tests/snapshots/visitor__function_positional_only_with_default.snap @@ -3,12 +3,12 @@ source: crates/ruff_python_ast/tests/visitor.rs expression: trace --- - StmtFunctionDef - - Arguments + - Parameters - ExprConstant - ExprConstant - - Arg - - Arg - - Arg - - Arg + - Parameter + - Parameter + - Parameter + - Parameter - StmtPass diff --git a/crates/ruff_python_ast/tests/snapshots/visitor__function_type_parameters.snap b/crates/ruff_python_ast/tests/snapshots/visitor__function_type_parameters.snap index d0ef547f65504..b0bbf8f550735 100644 --- a/crates/ruff_python_ast/tests/snapshots/visitor__function_type_parameters.snap +++ b/crates/ruff_python_ast/tests/snapshots/visitor__function_type_parameters.snap @@ -8,7 +8,7 @@ expression: trace - TypeParamTypeVar - TypeParamTypeVarTuple - TypeParamParamSpec - - Arguments + - Parameters - StmtExpr - ExprConstant diff --git a/crates/ruff_python_ast/tests/stmt_if.rs b/crates/ruff_python_ast/tests/stmt_if.rs index 178ec28dbc34e..73d156ae09c55 100644 --- a/crates/ruff_python_ast/tests/stmt_if.rs +++ b/crates/ruff_python_ast/tests/stmt_if.rs @@ -1,6 +1,6 @@ use ruff_python_ast::stmt_if::elif_else_range; -use ruff_python_ast::Stmt; -use ruff_python_parser::{Parse, ParseError}; + +use ruff_python_parser::{parse_suite, ParseError}; use ruff_text_size::TextSize; #[test] @@ -10,8 +10,11 @@ fn extract_elif_else_range() -> Result<(), ParseError> { elif b: ... "; - let stmt = Stmt::parse(contents, "")?; - let stmt = Stmt::as_if_stmt(&stmt).unwrap(); + let mut stmts = parse_suite(contents, "")?; + let stmt = stmts + .pop() + .and_then(ruff_python_ast::Stmt::if_stmt) + .unwrap(); let range = elif_else_range(&stmt.elif_else_clauses[0], contents).unwrap(); assert_eq!(range.start(), TextSize::from(14)); assert_eq!(range.end(), TextSize::from(18)); @@ -21,8 +24,11 @@ elif b: else: ... "; - let stmt = Stmt::parse(contents, "")?; - let stmt = Stmt::as_if_stmt(&stmt).unwrap(); + let mut stmts = parse_suite(contents, "")?; + let stmt = stmts + .pop() + .and_then(ruff_python_ast::Stmt::if_stmt) + .unwrap(); let range = elif_else_range(&stmt.elif_else_clauses[0], contents).unwrap(); assert_eq!(range.start(), TextSize::from(14)); assert_eq!(range.end(), TextSize::from(18)); diff --git a/crates/ruff_python_ast/tests/visitor.rs b/crates/ruff_python_ast/tests/visitor.rs index 11f19579cfa9b..b44cf55ce0324 100644 --- a/crates/ruff_python_ast/tests/visitor.rs +++ b/crates/ruff_python_ast/tests/visitor.rs @@ -7,13 +7,13 @@ use ruff_python_parser::{parse_tokens, Mode}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::{ - walk_alias, walk_arg, walk_arguments, walk_comprehension, walk_except_handler, walk_expr, - walk_keyword, walk_match_case, walk_pattern, walk_stmt, walk_type_param, walk_with_item, + walk_alias, walk_comprehension, walk_except_handler, walk_expr, walk_keyword, walk_match_case, + walk_parameter, walk_parameters, walk_pattern, walk_stmt, walk_type_param, walk_with_item, Visitor, }; use ruff_python_ast::{ - Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, ExceptHandler, Expr, Keyword, MatchCase, - Operator, Pattern, Stmt, TypeParam, UnaryOp, WithItem, + Alias, BoolOp, CmpOp, Comprehension, ExceptHandler, Expr, Keyword, MatchCase, Operator, + Parameter, Parameters, Pattern, Stmt, TypeParam, UnaryOp, WithItem, }; #[test] @@ -234,15 +234,15 @@ impl Visitor<'_> for RecordVisitor { self.exit_node(); } - fn visit_arguments(&mut self, arguments: &Arguments) { - self.enter_node(arguments); - walk_arguments(self, arguments); + fn visit_parameters(&mut self, parameters: &Parameters) { + self.enter_node(parameters); + walk_parameters(self, parameters); self.exit_node(); } - fn visit_arg(&mut self, arg: &Arg) { - self.enter_node(arg); - walk_arg(self, arg); + fn visit_parameter(&mut self, parameter: &Parameter) { + self.enter_node(parameter); + walk_parameter(self, parameter); self.exit_node(); } diff --git a/crates/ruff_python_codegen/src/generator.rs b/crates/ruff_python_codegen/src/generator.rs index a48416c21a706..4408ff9f05d5e 100644 --- a/crates/ruff_python_codegen/src/generator.rs +++ b/crates/ruff_python_codegen/src/generator.rs @@ -1,12 +1,12 @@ //! Generate Python source code from an abstract syntax tree (AST). -use ruff_python_ast::ArgWithDefault; +use ruff_python_ast::{ParameterWithDefault, TypeParams}; use std::ops::Deref; use ruff_python_ast::{ - self as ast, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, ConversionFlag, - DebugText, ExceptHandler, Expr, Identifier, MatchCase, Operator, Pattern, Stmt, Suite, - TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, WithItem, + self as ast, Alias, BoolOp, CmpOp, Comprehension, Constant, ConversionFlag, DebugText, + ExceptHandler, Expr, Identifier, MatchCase, Operator, Parameter, Parameters, Pattern, Stmt, + Suite, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, WithItem, }; use ruff_python_literal::escape::{AsciiEscape, Escape, UnicodeEscape}; @@ -23,7 +23,6 @@ mod precedence { pub(crate) const YIELD_FROM: u8 = 7; pub(crate) const IF: u8 = 9; pub(crate) const FOR: u8 = 9; - pub(crate) const ASYNC_FOR: u8 = 9; pub(crate) const WHILE: u8 = 9; pub(crate) const RETURN: u8 = 11; pub(crate) const SLICE: u8 = 13; @@ -204,8 +203,9 @@ impl<'a> Generator<'a> { match ast { Stmt::FunctionDef(ast::StmtFunctionDef { + is_async, name, - args, + parameters, body, returns, decorator_list, @@ -220,45 +220,16 @@ impl<'a> Generator<'a> { }); } statement!({ + if *is_async { + self.p("async "); + } self.p("def "); self.p_id(name); - self.unparse_type_params(type_params); - self.p("("); - self.unparse_args(args); - self.p(")"); - if let Some(returns) = returns { - self.p(" -> "); - self.unparse_expr(returns, precedence::MAX); + if let Some(type_params) = type_params { + self.unparse_type_params(type_params); } - self.p(":"); - }); - self.body(body); - if self.indent_depth == 0 { - self.newlines(2); - } - } - Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - name, - args, - body, - returns, - decorator_list, - type_params, - .. - }) => { - self.newlines(if self.indent_depth == 0 { 2 } else { 1 }); - for decorator in decorator_list { - statement!({ - self.p("@"); - self.unparse_expr(&decorator.expression, precedence::MAX); - }); - } - statement!({ - self.p("async def "); - self.p_id(name); - self.unparse_type_params(type_params); self.p("("); - self.unparse_args(args); + self.unparse_parameters(parameters); self.p(")"); if let Some(returns) = returns { self.p(" -> "); @@ -273,8 +244,7 @@ impl<'a> Generator<'a> { } Stmt::ClassDef(ast::StmtClassDef { name, - bases, - keywords, + arguments, body, decorator_list, type_params, @@ -290,25 +260,28 @@ impl<'a> Generator<'a> { statement!({ self.p("class "); self.p_id(name); - self.unparse_type_params(type_params); - let mut first = true; - for base in bases { - self.p_if(first, "("); - self.p_delim(&mut first, ", "); - self.unparse_expr(base, precedence::MAX); + if let Some(type_params) = type_params { + self.unparse_type_params(type_params); } - for keyword in keywords { - self.p_if(first, "("); - self.p_delim(&mut first, ", "); - if let Some(arg) = &keyword.arg { - self.p_id(arg); - self.p("="); - } else { - self.p("**"); + if let Some(arguments) = arguments { + self.p("("); + let mut first = true; + for base in &arguments.args { + self.p_delim(&mut first, ", "); + self.unparse_expr(base, precedence::MAX); } - self.unparse_expr(&keyword.value, precedence::MAX); + for keyword in &arguments.keywords { + self.p_delim(&mut first, ", "); + if let Some(arg) = &keyword.arg { + self.p_id(arg); + self.p("="); + } else { + self.p("**"); + } + self.unparse_expr(&keyword.value, precedence::MAX); + } + self.p(")"); } - self.p_if(!first, ")"); self.p(":"); }); self.body(body); @@ -316,10 +289,7 @@ impl<'a> Generator<'a> { self.newlines(2); } } - Stmt::Return(ast::StmtReturn { - value, - range: _range, - }) => { + Stmt::Return(ast::StmtReturn { value, range: _ }) => { statement!({ if let Some(expr) = value { self.p("return "); @@ -329,10 +299,7 @@ impl<'a> Generator<'a> { } }); } - Stmt::Delete(ast::StmtDelete { - targets, - range: _range, - }) => { + Stmt::Delete(ast::StmtDelete { targets, range: _ }) => { statement!({ self.p("del "); let mut first = true; @@ -355,7 +322,7 @@ impl<'a> Generator<'a> { target, op, value, - range: _range, + range: _, }) => { statement!({ self.unparse_expr(target, precedence::AUG_ASSIGN); @@ -384,7 +351,7 @@ impl<'a> Generator<'a> { annotation, value, simple, - range: _range, + range: _, }) => { statement!({ let need_parens = matches!(target.as_ref(), Expr::Name(_)) && !simple; @@ -400,6 +367,7 @@ impl<'a> Generator<'a> { }); } Stmt::For(ast::StmtFor { + is_async, target, iter, body, @@ -407,6 +375,9 @@ impl<'a> Generator<'a> { .. }) => { statement!({ + if *is_async { + self.p("async "); + } self.p("for "); self.unparse_expr(target, precedence::FOR); self.p(" in "); @@ -421,33 +392,11 @@ impl<'a> Generator<'a> { self.body(orelse); } } - Stmt::AsyncFor(ast::StmtAsyncFor { - target, - iter, - body, - orelse, - .. - }) => { - statement!({ - self.p("async for "); - self.unparse_expr(target, precedence::ASYNC_FOR); - self.p(" in "); - self.unparse_expr(iter, precedence::MAX); - self.p(":"); - }); - self.body(body); - if !orelse.is_empty() { - statement!({ - self.p("else:"); - }); - self.body(orelse); - } - } Stmt::While(ast::StmtWhile { test, body, orelse, - range: _range, + range: _, }) => { statement!({ self.p("while "); @@ -466,7 +415,7 @@ impl<'a> Generator<'a> { test, body, elif_else_clauses, - range: _range, + range: _, }) => { statement!({ self.p("if "); @@ -490,21 +439,17 @@ impl<'a> Generator<'a> { self.body(&clause.body); } } - Stmt::With(ast::StmtWith { items, body, .. }) => { + Stmt::With(ast::StmtWith { + is_async, + items, + body, + .. + }) => { statement!({ - self.p("with "); - let mut first = true; - for item in items { - self.p_delim(&mut first, ", "); - self.unparse_with_item(item); + if *is_async { + self.p("async "); } - self.p(":"); - }); - self.body(body); - } - Stmt::AsyncWith(ast::StmtAsyncWith { items, body, .. }) => { - statement!({ - self.p("async with "); + self.p("with "); let mut first = true; for item in items { self.p_delim(&mut first, ", "); @@ -517,7 +462,7 @@ impl<'a> Generator<'a> { Stmt::Match(ast::StmtMatch { subject, cases, - range: _range, + range: _, }) => { statement!({ self.p("match "); @@ -534,20 +479,22 @@ impl<'a> Generator<'a> { } Stmt::TypeAlias(ast::StmtTypeAlias { name, - range: _range, + range: _, type_params, value, }) => { self.p("type "); self.unparse_expr(name, precedence::MAX); - self.unparse_type_params(type_params); + if let Some(type_params) = type_params { + self.unparse_type_params(type_params); + } self.p(" = "); self.unparse_expr(value, precedence::ASSIGN); } Stmt::Raise(ast::StmtRaise { exc, cause, - range: _range, + range: _, }) => { statement!({ self.p("raise"); @@ -566,38 +513,8 @@ impl<'a> Generator<'a> { handlers, orelse, finalbody, - range: _range, - }) => { - statement!({ - self.p("try:"); - }); - self.body(body); - - for handler in handlers { - statement!({ - self.unparse_except_handler(handler, false); - }); - } - - if !orelse.is_empty() { - statement!({ - self.p("else:"); - }); - self.body(orelse); - } - if !finalbody.is_empty() { - statement!({ - self.p("finally:"); - }); - self.body(finalbody); - } - } - Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, + is_star, + range: _, }) => { statement!({ self.p("try:"); @@ -606,7 +523,7 @@ impl<'a> Generator<'a> { for handler in handlers { statement!({ - self.unparse_except_handler(handler, true); + self.unparse_except_handler(handler, *is_star); }); } @@ -626,7 +543,7 @@ impl<'a> Generator<'a> { Stmt::Assert(ast::StmtAssert { test, msg, - range: _range, + range: _, }) => { statement!({ self.p("assert "); @@ -637,10 +554,7 @@ impl<'a> Generator<'a> { } }); } - Stmt::Import(ast::StmtImport { - names, - range: _range, - }) => { + Stmt::Import(ast::StmtImport { names, range: _ }) => { statement!({ self.p("import "); let mut first = true; @@ -654,7 +568,7 @@ impl<'a> Generator<'a> { module, names, level, - range: _range, + range: _, }) => { statement!({ self.p("from "); @@ -672,10 +586,7 @@ impl<'a> Generator<'a> { } }); } - Stmt::Global(ast::StmtGlobal { - names, - range: _range, - }) => { + Stmt::Global(ast::StmtGlobal { names, range: _ }) => { statement!({ self.p("global "); let mut first = true; @@ -685,10 +596,7 @@ impl<'a> Generator<'a> { } }); } - Stmt::Nonlocal(ast::StmtNonlocal { - names, - range: _range, - }) => { + Stmt::Nonlocal(ast::StmtNonlocal { names, range: _ }) => { statement!({ self.p("nonlocal "); let mut first = true; @@ -698,10 +606,7 @@ impl<'a> Generator<'a> { } }); } - Stmt::Expr(ast::StmtExpr { - value, - range: _range, - }) => { + Stmt::Expr(ast::StmtExpr { value, range: _ }) => { statement!({ self.unparse_expr(value, precedence::EXPR); }); @@ -721,7 +626,7 @@ impl<'a> Generator<'a> { self.p("continue"); }); } - Stmt::LineMagic(ast::StmtLineMagic { kind, value, .. }) => { + Stmt::IpyEscapeCommand(ast::StmtIpyEscapeCommand { kind, value, .. }) => { statement!({ self.p(&format!("{kind}{value}")); }); @@ -735,7 +640,7 @@ impl<'a> Generator<'a> { type_, name, body, - range: _range, + range: _, }) => { self.p("except"); if star { @@ -757,22 +662,13 @@ impl<'a> Generator<'a> { fn unparse_pattern(&mut self, ast: &Pattern) { match ast { - Pattern::MatchValue(ast::PatternMatchValue { - value, - range: _range, - }) => { + Pattern::MatchValue(ast::PatternMatchValue { value, range: _ }) => { self.unparse_expr(value, precedence::MAX); } - Pattern::MatchSingleton(ast::PatternMatchSingleton { - value, - range: _range, - }) => { + Pattern::MatchSingleton(ast::PatternMatchSingleton { value, range: _ }) => { self.unparse_constant(value); } - Pattern::MatchSequence(ast::PatternMatchSequence { - patterns, - range: _range, - }) => { + Pattern::MatchSequence(ast::PatternMatchSequence { patterns, range: _ }) => { self.p("["); let mut first = true; for pattern in patterns { @@ -785,7 +681,7 @@ impl<'a> Generator<'a> { keys, patterns, rest, - range: _range, + range: _, }) => { self.p("{"); let mut first = true; @@ -803,10 +699,7 @@ impl<'a> Generator<'a> { self.p("}"); } Pattern::MatchClass(_) => {} - Pattern::MatchStar(ast::PatternMatchStar { - name, - range: _range, - }) => { + Pattern::MatchStar(ast::PatternMatchStar { name, range: _ }) => { self.p("*"); if let Some(name) = name { self.p_id(name); @@ -817,7 +710,7 @@ impl<'a> Generator<'a> { Pattern::MatchAs(ast::PatternMatchAs { pattern, name, - range: _range, + range: _, }) => { if let Some(pattern) = pattern { self.unparse_pattern(pattern); @@ -829,10 +722,7 @@ impl<'a> Generator<'a> { self.p("_"); } } - Pattern::MatchOr(ast::PatternMatchOr { - patterns, - range: _range, - }) => { + Pattern::MatchOr(ast::PatternMatchOr { patterns, range: _ }) => { let mut first = true; for pattern in patterns { self.p_delim(&mut first, " | "); @@ -853,16 +743,14 @@ impl<'a> Generator<'a> { self.body(&ast.body); } - fn unparse_type_params(&mut self, type_params: &Vec) { - if !type_params.is_empty() { - self.p("["); - let mut first = true; - for type_param in type_params { - self.p_delim(&mut first, ", "); - self.unparse_type_param(type_param); - } - self.p("]"); + fn unparse_type_params(&mut self, type_params: &TypeParams) { + self.p("["); + let mut first = true; + for type_param in type_params.iter() { + self.p_delim(&mut first, ", "); + self.unparse_type_param(type_param); } + self.p("]"); } pub(crate) fn unparse_type_param(&mut self, ast: &TypeParam) { @@ -912,7 +800,7 @@ impl<'a> Generator<'a> { Expr::BoolOp(ast::ExprBoolOp { op, values, - range: _range, + range: _, }) => { let (op, prec) = opprec!(bin, op, BoolOp, And("and", AND), Or("or", OR)); group_if!(prec, { @@ -926,7 +814,7 @@ impl<'a> Generator<'a> { Expr::NamedExpr(ast::ExprNamedExpr { target, value, - range: _range, + range: _, }) => { group_if!(precedence::NAMED_EXPR, { self.unparse_expr(target, precedence::NAMED_EXPR); @@ -938,7 +826,7 @@ impl<'a> Generator<'a> { left, op, right, - range: _range, + range: _, }) => { let rassoc = matches!(op, Operator::Pow); let (op, prec) = opprec!( @@ -968,7 +856,7 @@ impl<'a> Generator<'a> { Expr::UnaryOp(ast::ExprUnaryOp { op, operand, - range: _range, + range: _, }) => { let (op, prec) = opprec!( un, @@ -985,14 +873,16 @@ impl<'a> Generator<'a> { }); } Expr::Lambda(ast::ExprLambda { - args, + parameters, body, - range: _range, + range: _, }) => { group_if!(precedence::LAMBDA, { - let npos = args.args.len() + args.posonlyargs.len(); - self.p(if npos > 0 { "lambda " } else { "lambda" }); - self.unparse_args(args); + self.p("lambda"); + if let Some(parameters) = parameters { + self.p(" "); + self.unparse_parameters(parameters); + } self.p(": "); self.unparse_expr(body, precedence::LAMBDA); }); @@ -1001,7 +891,7 @@ impl<'a> Generator<'a> { test, body, orelse, - range: _range, + range: _, }) => { group_if!(precedence::IF_EXP, { self.unparse_expr(body, precedence::IF_EXP + 1); @@ -1014,7 +904,7 @@ impl<'a> Generator<'a> { Expr::Dict(ast::ExprDict { keys, values, - range: _range, + range: _, }) => { self.p("{"); let mut first = true; @@ -1031,10 +921,7 @@ impl<'a> Generator<'a> { } self.p("}"); } - Expr::Set(ast::ExprSet { - elts, - range: _range, - }) => { + Expr::Set(ast::ExprSet { elts, range: _ }) => { if elts.is_empty() { self.p("set()"); } else { @@ -1050,7 +937,7 @@ impl<'a> Generator<'a> { Expr::ListComp(ast::ExprListComp { elt, generators, - range: _range, + range: _, }) => { self.p("["); self.unparse_expr(elt, precedence::COMPREHENSION_ELEMENT); @@ -1060,7 +947,7 @@ impl<'a> Generator<'a> { Expr::SetComp(ast::ExprSetComp { elt, generators, - range: _range, + range: _, }) => { self.p("{"); self.unparse_expr(elt, precedence::COMPREHENSION_ELEMENT); @@ -1071,7 +958,7 @@ impl<'a> Generator<'a> { key, value, generators, - range: _range, + range: _, }) => { self.p("{"); self.unparse_expr(key, precedence::COMPREHENSION_ELEMENT); @@ -1083,26 +970,20 @@ impl<'a> Generator<'a> { Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, - range: _range, + range: _, }) => { self.p("("); self.unparse_expr(elt, precedence::COMPREHENSION_ELEMENT); self.unparse_comp(generators); self.p(")"); } - Expr::Await(ast::ExprAwait { - value, - range: _range, - }) => { + Expr::Await(ast::ExprAwait { value, range: _ }) => { group_if!(precedence::AWAIT, { self.p("await "); self.unparse_expr(value, precedence::MAX); }); } - Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => { + Expr::Yield(ast::ExprYield { value, range: _ }) => { group_if!(precedence::YIELD, { self.p("yield"); if let Some(value) = value { @@ -1111,10 +992,7 @@ impl<'a> Generator<'a> { } }); } - Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) => { + Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) => { group_if!(precedence::YIELD_FROM, { self.p("yield from "); self.unparse_expr(value, precedence::MAX); @@ -1124,7 +1002,7 @@ impl<'a> Generator<'a> { left, ops, comparators, - range: _range, + range: _, }) => { group_if!(precedence::CMP, { let new_lvl = precedence::CMP + 1; @@ -1149,9 +1027,8 @@ impl<'a> Generator<'a> { } Expr::Call(ast::ExprCall { func, - args, - keywords, - range: _range, + arguments, + range: _, }) => { self.unparse_expr(func, precedence::MAX); self.p("("); @@ -1159,21 +1036,21 @@ impl<'a> Generator<'a> { [Expr::GeneratorExp(ast::ExprGeneratorExp { elt, generators, - range: _range, + range: _, })], [], - ) = (args.as_slice(), keywords.as_slice()) + ) = (arguments.args.as_slice(), arguments.keywords.as_slice()) { // Ensure that a single generator doesn't get double-parenthesized. self.unparse_expr(elt, precedence::COMMA); self.unparse_comp(generators); } else { let mut first = true; - for arg in args { + for arg in &arguments.args { self.p_delim(&mut first, ", "); self.unparse_expr(arg, precedence::COMMA); } - for kw in keywords { + for kw in &arguments.keywords { self.p_delim(&mut first, ", "); if let Some(arg) = &kw.arg { self.p_id(arg); @@ -1192,23 +1069,20 @@ impl<'a> Generator<'a> { debug_text, conversion, format_spec, - range: _range, + range: _, }) => self.unparse_formatted( value, debug_text.as_ref(), *conversion, format_spec.as_deref(), ), - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { - self.unparse_joinedstr(values, false); + Expr::FString(ast::ExprFString { values, .. }) => { + self.unparse_f_string(values, false); } Expr::Constant(ast::ExprConstant { value, kind, - range: _range, + range: _, }) => { if let Some(kind) = kind { self.p(kind); @@ -1268,7 +1142,7 @@ impl<'a> Generator<'a> { lower, upper, step, - range: _range, + range: _, }) => { if let Some(lower) = lower { self.unparse_expr(lower, precedence::SLICE); @@ -1282,7 +1156,7 @@ impl<'a> Generator<'a> { self.unparse_expr(step, precedence::SLICE); } } - Expr::LineMagic(ast::ExprLineMagic { kind, value, .. }) => { + Expr::IpyEscapeCommand(ast::ExprIpyEscapeCommand { kind, value, .. }) => { self.p(&format!("{kind}{value}")); } } @@ -1295,8 +1169,8 @@ impl<'a> Generator<'a> { Constant::Bytes(b) => { self.p_bytes_repr(b); } - Constant::Str(s) => { - self.p_str_repr(s); + Constant::Str(ast::StringConstant { value, .. }) => { + self.p_str_repr(value); } Constant::None => self.p("None"), Constant::Bool(b) => self.p(if *b { "True" } else { "False" }), @@ -1324,42 +1198,47 @@ impl<'a> Generator<'a> { } } - fn unparse_args(&mut self, args: &Arguments) { + fn unparse_parameters(&mut self, parameters: &Parameters) { let mut first = true; - for (i, arg_with_default) in args.posonlyargs.iter().chain(&args.args).enumerate() { + for (i, parameter_with_default) in parameters + .posonlyargs + .iter() + .chain(¶meters.args) + .enumerate() + { self.p_delim(&mut first, ", "); - self.unparse_arg_with_default(arg_with_default); - self.p_if(i + 1 == args.posonlyargs.len(), ", /"); + self.unparse_parameter_with_default(parameter_with_default); + self.p_if(i + 1 == parameters.posonlyargs.len(), ", /"); } - if args.vararg.is_some() || !args.kwonlyargs.is_empty() { + if parameters.vararg.is_some() || !parameters.kwonlyargs.is_empty() { self.p_delim(&mut first, ", "); self.p("*"); } - if let Some(vararg) = &args.vararg { - self.unparse_arg(vararg); + if let Some(vararg) = ¶meters.vararg { + self.unparse_parameter(vararg); } - for kwarg in &args.kwonlyargs { + for kwarg in ¶meters.kwonlyargs { self.p_delim(&mut first, ", "); - self.unparse_arg_with_default(kwarg); + self.unparse_parameter_with_default(kwarg); } - if let Some(kwarg) = &args.kwarg { + if let Some(kwarg) = ¶meters.kwarg { self.p_delim(&mut first, ", "); self.p("**"); - self.unparse_arg(kwarg); + self.unparse_parameter(kwarg); } } - fn unparse_arg(&mut self, arg: &Arg) { - self.p_id(&arg.arg); - if let Some(ann) = &arg.annotation { + fn unparse_parameter(&mut self, parameter: &Parameter) { + self.p_id(¶meter.name); + if let Some(ann) = ¶meter.annotation { self.p(": "); self.unparse_expr(ann, precedence::COMMA); } } - fn unparse_arg_with_default(&mut self, arg_with_default: &ArgWithDefault) { - self.unparse_arg(&arg_with_default.def); - if let Some(default) = &arg_with_default.default { + fn unparse_parameter_with_default(&mut self, parameter_with_default: &ParameterWithDefault) { + self.unparse_parameter(¶meter_with_default.parameter); + if let Some(default) = ¶meter_with_default.default { self.p("="); self.unparse_expr(default, precedence::COMMA); } @@ -1382,9 +1261,9 @@ impl<'a> Generator<'a> { } } - fn unparse_fstring_body(&mut self, values: &[Expr], is_spec: bool) { + fn unparse_f_string_body(&mut self, values: &[Expr], is_spec: bool) { for value in values { - self.unparse_fstring_elem(value, is_spec); + self.unparse_f_string_elem(value, is_spec); } } @@ -1423,33 +1302,30 @@ impl<'a> Generator<'a> { if let Some(spec) = spec { self.p(":"); - self.unparse_fstring_elem(spec, true); + self.unparse_f_string_elem(spec, true); } self.p("}"); } - fn unparse_fstring_elem(&mut self, expr: &Expr, is_spec: bool) { + fn unparse_f_string_elem(&mut self, expr: &Expr, is_spec: bool) { match expr { Expr::Constant(ast::ExprConstant { value, .. }) => { - if let Constant::Str(s) = value { - self.unparse_fstring_str(s); + if let Constant::Str(ast::StringConstant { value, .. }) = value { + self.unparse_f_string_literal(value); } else { unreachable!() } } - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { - self.unparse_joinedstr(values, is_spec); + Expr::FString(ast::ExprFString { values, .. }) => { + self.unparse_f_string(values, is_spec); } Expr::FormattedValue(ast::ExprFormattedValue { value, debug_text, conversion, format_spec, - range: _range, + range: _, }) => self.unparse_formatted( value, debug_text.as_ref(), @@ -1460,14 +1336,14 @@ impl<'a> Generator<'a> { } } - fn unparse_fstring_str(&mut self, s: &str) { + fn unparse_f_string_literal(&mut self, s: &str) { let s = s.replace('{', "{{").replace('}', "}}"); self.p(&s); } - fn unparse_joinedstr(&mut self, values: &[Expr], is_spec: bool) { + fn unparse_f_string(&mut self, values: &[Expr], is_spec: bool) { if is_spec { - self.unparse_fstring_body(values, is_spec); + self.unparse_f_string_body(values, is_spec); } else { self.p("f"); let mut generator = Generator::new( @@ -1478,7 +1354,7 @@ impl<'a> Generator<'a> { }, self.line_ending, ); - generator.unparse_fstring_body(values, is_spec); + generator.unparse_f_string_body(values, is_spec); let body = &generator.buffer; self.p_str_repr(body); } @@ -1503,8 +1379,8 @@ impl<'a> Generator<'a> { #[cfg(test)] mod tests { - use ruff_python_ast::{Mod, ModModule, Stmt}; - use ruff_python_parser::{self, Mode, Parse}; + use ruff_python_ast::{Mod, ModModule}; + use ruff_python_parser::{self, parse_suite, Mode}; use ruff_source_file::LineEnding; @@ -1515,9 +1391,9 @@ mod tests { let indentation = Indentation::default(); let quote = Quote::default(); let line_ending = LineEnding::default(); - let stmt = Stmt::parse(contents, "").unwrap(); + let stmt = parse_suite(contents, "").unwrap(); let mut generator = Generator::new(&indentation, quote, line_ending); - generator.unparse_stmt(&stmt); + generator.unparse_suite(&stmt); generator.generate() } @@ -1527,9 +1403,9 @@ mod tests { line_ending: LineEnding, contents: &str, ) -> String { - let stmt = Stmt::parse(contents, "").unwrap(); + let stmt = parse_suite(contents, "").unwrap(); let mut generator = Generator::new(indentation, quote, line_ending); - generator.unparse_stmt(&stmt); + generator.unparse_suite(&stmt); generator.generate() } diff --git a/crates/ruff_python_codegen/src/lib.rs b/crates/ruff_python_codegen/src/lib.rs index 067d1d5b3e35e..a0bf9fcd4f625 100644 --- a/crates/ruff_python_codegen/src/lib.rs +++ b/crates/ruff_python_codegen/src/lib.rs @@ -2,15 +2,14 @@ mod generator; mod stylist; pub use generator::Generator; -use ruff_python_ast::Suite; -use ruff_python_parser::{lexer, Mode, Parse, ParseError}; +use ruff_python_parser::{lexer, parse_suite, Mode, ParseError}; use ruff_source_file::Locator; pub use stylist::{Quote, Stylist}; /// Run round-trip source code generation on a given Python code. pub fn round_trip(code: &str, source_path: &str) -> Result { let locator = Locator::new(code); - let python_ast = Suite::parse(code, source_path)?; + let python_ast = parse_suite(code, source_path)?; let tokens: Vec<_> = lexer::lex(code, Mode::Module).collect(); let stylist = Stylist::from_tokens(&tokens, &locator); let mut generator: Generator = (&stylist).into(); diff --git a/crates/ruff_python_formatter/Cargo.toml b/crates/ruff_python_formatter/Cargo.toml index 1f722f0a79a7e..e63bbeb8720b7 100644 --- a/crates/ruff_python_formatter/Cargo.toml +++ b/crates/ruff_python_formatter/Cargo.toml @@ -25,14 +25,16 @@ clap = { workspace = true } countme = "3.0.1" is-macro = { workspace = true } itertools = { workspace = true } +memchr = { workspace = true } once_cell = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true, optional = true } smallvec = { workspace = true } thiserror = { workspace = true } +unicode-width = { workspace = true } [dev-dependencies] -ruff_formatter = { path = "../ruff_formatter", features = ["serde"]} +ruff_formatter = { path = "../ruff_formatter", features = ["serde"] } insta = { workspace = true, features = ["glob"] } serde = { workspace = true } @@ -43,8 +45,8 @@ similar = { workspace = true } name = "ruff_python_formatter_fixtures" path = "tests/fixtures.rs" test = true -required-features = [ "serde" ] +required-features = ["serde"] [features] -serde = ["dep:serde", "ruff_formatter/serde", "ruff_source_file/serde"] +serde = ["dep:serde", "ruff_formatter/serde", "ruff_source_file/serde", "ruff_python_ast/serde"] default = ["serde"] diff --git a/crates/ruff_python_formatter/README.md b/crates/ruff_python_formatter/README.md index 6c7ecc6ccac55..11f306bf62116 100644 --- a/crates/ruff_python_formatter/README.md +++ b/crates/ruff_python_formatter/README.md @@ -3,10 +3,205 @@ The goal of our formatter is to be compatible with Black except for rare edge cases (mostly involving comment placement). -## Implementing a node +## Dev tools -Formatting each node follows roughly the same structure. We start with a `Format{{Node}}` struct -that implements Default (and `AsFormat`/`IntoFormat` impls in `generated.rs`, see orphan rules below). +**Testing your changes** You can use the `ruff_python_formatter` binary to format individual files +and show debug info. It's fast to compile because it doesn't depend on `ruff`. The easiest way is to +create a `scratch.py` (or `scratch.pyi`) in the project root and run + +```shell +cargo run --bin ruff_python_formatter -- --emit stdout scratch.py +``` + +which has `--print-ir` and `--print-comments` options. We especially recommend `--print-comments`. + +
+Usage example + +Command + +```shell +cargo run --bin ruff_python_formatter -- --emit stdout --print-comments --print-ir scratch.py +``` + +Input + +```python +def f(): # a + pass +``` + +Output + +```text +[ + "def f", + group([group(["()"]), source_position(7)]), + ":", + line_suffix([" # a"]), + expand_parent, + indent([hard_line_break, "pass", source_position(21)]), + hard_line_break, + source_position(21), + hard_line_break, + source_position(22) +] +{ + Node { + kind: StmtFunctionDef, + range: 0..21, + source: `def f(): # a⏎`, + }: { + "leading": [], + "dangling": [ + SourceComment { + text: "# a", + position: EndOfLine, + formatted: true, + }, + ], + "trailing": [], + }, +} +def f(): # a + pass +``` + +
+ +The other option is to use the playground (also check the playground README): + +```shell +cd playground && npm install && npm run dev:wasm && npm run dev +``` + +Run`npm run dev:wasm` and reload the page in the browser to refresh. + +**Tests** Running the entire ruff test suite is slow, `cargo test -p ruff_python_formatter` is a +lot faster. We use [insta](https://insta.rs/) to create snapshots of all tests in +`crates/ruff_python_formatter/resources/test/fixtures/ruff`. We have copied the majority of tests +over from Black to check the difference between Ruff and Black output. Whenever we have no more +differences on a Black input file, the snapshot is deleted. + +**Ecosystem checks** `scripts/formatter_ecosystem_checks.sh` runs Black compatibility and stability +checks on a number of selected projects. It will print the similarity index, the percentage of lines +that remains unchanged between Black's formatting and our formatting. You could compute it as the +number of neutral lines in a diff divided by the neutral plus the removed lines. We run this script +in CI, you can view the results in a PR page under "Checks" > "CI" > "Summary" at the bottom of the +page. The stability checks catch for three common problems: The second +formatting pass looks different than the first (formatter instability or lack of idempotency), +printing invalid syntax (e.g. missing parentheses around multiline expressions) and panics (mostly +in debug assertions). You should ensure that your changes don't decrease the similarity index. + +**Terminology** For `()`, `[]` and `{}` we use the following terminology: + +- Parentheses: `(`, `)` or all kind of parentheses (`()`, `[]` and `{}`, e.g. + `has_own_parentheses`) +- Brackets: `[`, `]` +- Braces: `{`, `}` + +## `format_dev` + +It's possible to format an entire project: + +```shell +cargo run --bin ruff_dev -- format-dev --write /path/to/my_project +``` + +Available options: + +- `--write`: Format the files and write them back to disk. +- `--stability-check`: Format twice (but don't write to disk without `--write`) and check for + differences and crashes. +- `--multi-project`: Treat every subdirectory as a separate project. Useful for ecosystem checks. +- `--error-file`: Write all errors to the given file. +- `--log-file`: Write all messages to the given file. +- `--stats-file`: Use together with `--multi-project`, this writes the similarity index as unicode + table to the given file. + +**Large ecosystem checks** It is also possible to check a large number of repositories. This dataset +is large (~60GB), so we only do this occasionally: + +```shell +# Get the list of projects +curl https://raw.githubusercontent.com/akx/ruff-usage-aggregate/master/data/known-github-tomls-clean.jsonl > github_search.jsonl +# Repurpose this script to download the repositories for us +python scripts/check_ecosystem.py --checkouts target/checkouts --projects github_search.jsonl -v $(which true) $(which true) +# Check each project for formatter stability +cargo run --bin ruff_dev -- format-dev --stability-check --error-file target/formatter-ecosystem-errors.txt --multi-project target/checkouts +``` + +**Shrinking** To shrink a formatter error from an entire file to a minimal reproducible example, +you can use `ruff_shrinking`: + +```shell +cargo run --bin ruff_shrinking -- target/shrinking.py "Unstable formatting" "target/debug/ruff_dev format-dev --stability-check target/shrinking.py" +``` + +The first argument is the input file, the second is the output file where the candidates +and the eventual minimized version will be written to. The third argument is a regex matching the +error message, e.g. "Unstable formatting" or "Formatter error". The last argument is the command +with the error, e.g. running the stability check on the candidate file. The script will try various +strategies to remove parts of the code. If the output of the command still matches, it will use that +slightly smaller code as starting point for the next iteration, otherwise it will revert and try +a different strategy until all strategies are exhausted. + +## Helper structs + +To abstract formatting something into a helper, create a new struct with the data you want to +format and implement `Format> for MyStruct`. Below is a small dummy example. + +```rust +/// Helper to hide the fields for the struct +pub(crate) fn empty_parenthesized<'content>( + comments: &'content [SourceComment], + has_plus_prefix: bool, +) -> FormatEmptyParenthesized<'content> { + FormatEmptyParenthesized { + comments, + has_plus_prefix, + } +} + +/// The wrapper struct +pub(crate) struct FormatEmptyParenthesized<'content> { + comments: &'content [SourceComment], + has_plus_prefix: bool, +} + +impl Format> for FormatEmptyParenthesized<'_> { + /// Here we implement the actual formatting + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + if self.has_plus_prefix { + text("+").fmt(f)?; // This is equivalent to `write!(f, [text("*")])?;` + } + write!( + f, + [ + text("("), + soft_block_indent(&dangling_comments(&self.comments)), + text(")") + ] + ) + } +} +``` + +If the struct is used across modules, also adds constructor function that hides the fields of the +struct. Since it implements `Format`, you can directly use it in write calls: + +```rust +write!(f, [empty_parenthesized(dangling_end_of_line_comments)])?; +``` + +Check the `builders` module for existing primitives. + +## Adding new syntax + +Occasionally, Python will add new syntax. After adding it to `ruff_python_ast`, run `generate.py` +to generate stubs for node formatting. This will add a `Format{{Node}}` struct +that implements `Default` (and `AsFormat`/`IntoFormat` impls in `generated.rs`, see orphan rules +below). ```rust #[derive(Default)] @@ -47,8 +242,6 @@ impl FormatNodeRule for FormatStmtReturn { } ``` -Check the `builders` module for the primitives that you can use. - If something such as list or a tuple can break into multiple lines if it is too long for a single line, wrap it into a `group`. Ignoring comments, we could format a tuple with two items like this: @@ -177,10 +370,10 @@ the `break` and wrongly formatted as such. We can identify these cases by lookin between two bodies that have the same indentation level as the keyword, e.g. in our case the leading else comment is inside the `while` node (which spans the entire snippet) and on the same level as the `else`. We identify those case in -[`handle_in_between_bodies_own_line_comment`](https://github.com/astral-sh/ruff/blob/be11cae619d5a24adb4da34e64d3c5f270f9727b/crates/ruff_python_formatter/src/comments/placement.rs#L196) +[`handle_own_line_comment_around_body`](https://github.com/astral-sh/ruff/blob/4bdd99f8822d914a59f918fc46bbd17a88e2fe47/crates/ruff_python_formatter/src/comments/placement.rs#L390) and mark them as dangling for manual formatting later. Similarly, we find and mark comment after the colon(s) in -[`handle_trailing_end_of_line_condition_comment`](https://github.com/astral-sh/ruff/blob/main/crates/ruff_python_formatter/src/comments/placement.rs#L518) +[`handle_end_of_line_comment_around_body`](https://github.com/astral-sh/ruff/blob/4bdd99f8822d914a59f918fc46bbd17a88e2fe47/crates/ruff_python_formatter/src/comments/placement.rs#L238C4-L238C14) . The comments don't carry any extra information such as why we marked the comment as trailing, @@ -221,95 +414,6 @@ fn fmt_fields(&self, item: &StmtWhile, f: &mut PyFormatter) -> FormatResult<()> } ``` -## Development notes - -Handling parentheses and comments are two major challenges in a Python formatter. - -We have copied the majority of tests over from Black and use [insta](https://insta.rs/docs/cli/) for -snapshot testing with the diff between Ruff and Black, Black output and Ruff output. We put -additional test cases in `resources/test/fixtures/ruff`. - -The full Ruff test suite is slow, `cargo test -p ruff_python_formatter` is a lot faster. - -You can check the black compatibility on a number of projects using -`scripts/formatter_ecosystem_checks.sh`. It will print the similarity index, the percentage of lines -that remains unchanged between black's formatting and our formatting. You could compute it as the -number of neutral lines in a diff divided by the neutral plus the removed lines. It also checks for -common problems such unstable formatting, internal formatter errors and printing invalid syntax. We -run this script in CI and you can view the results in a PR page under "Checks" > "CI" > "Summary" at -the bottom of the page. - -There is a `ruff_python_formatter` binary that avoid building and linking the main `ruff` crate. - -You can use `scratch.py` as a playground, e.g. -`cargo run --bin ruff_python_formatter -- --emit stdout scratch.py`, which additional `--print-ir` -and `--print-comments` options. - -The origin of Ruff's formatter is the [Rome formatter](https://github.com/rome/tools/tree/main/crates/rome_json_formatter), -e.g. the ruff_formatter crate is forked from the [rome_formatter crate](https://github.com/rome/tools/tree/main/crates/rome_formatter). -The Rome repository can be a helpful reference when implementing something in the Ruff formatter. - -### Checking entire projects - -It's possible to format an entire project: - -```shell -cargo run --bin ruff_dev -- format-dev --write my_project -``` - -This will format all files that `ruff check` would lint and computes the similarity index, the -fraction of changed lines. The similarity index is 1 if there were no changes at all, while 0 means -we changed every single line. If you run this on a black formatted projects, this tells you how -similar the ruff formatter is to black for the given project, with our goal being as close to 1 as -possible. - -There are three common problems with the formatter: The second formatting pass looks different than -the first (formatter instability or lack of idempotency), we print invalid syntax (e.g. missing -parentheses around multiline expressions) and panics (mostly in debug assertions). We test for all -of these using the `--stability-check` option in the `format-dev` subcommand: - -The easiest is to check CPython: - -```shell -git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff/resources/test/cpython -cargo run --bin ruff_dev -- format-dev --stability-check crates/ruff/resources/test/cpython -``` - -Compared to `ruff check`, `cargo run --bin ruff_dev -- format-dev` has 4 additional options: - -- `--write`: Format the files and write them back to disk -- `--stability-check`: Format twice (but don't write to disk) and check for differences and crashes -- `--multi-project`: Treat every subdirectory as a separate project. Useful for ecosystem checks. -- `--error-file`: Use together with `--multi-project`, this writes all errors (but not status - messages) to a file. - -It is also possible to check a large number of repositories. This dataset is large (~60GB), so we -only do this occasionally: - -```shell -# Get the list of projects -curl https://raw.githubusercontent.com/akx/ruff-usage-aggregate/master/data/known-github-tomls-clean.jsonl > github_search.jsonl -# Repurpose this script to download the repositories for us -python scripts/check_ecosystem.py --checkouts target/checkouts --projects github_search.jsonl -v $(which true) $(which true) -# Check each project for formatter stability -cargo run --bin ruff_dev -- format-dev --stability-check --error-file target/formatter-ecosystem-errors.txt --multi-project target/checkouts -``` - -To shrink a formatter error from an entire file to a minimal reproducible example, you can use -`ruff_shrinking`: - -```shell -cargo run --bin ruff_shrinking -- target/shrinking.py "Unstable formatting" "target/release/ruff_dev format-dev --stability-check target/shrinking.py" -``` - -The first argument is the input file, the second is the output file where the candidates -and the eventual minimized version will be written to. The third argument is a regex matching the -error message, e.g. "Unstable formatting" or "Formatter error". The last argument is the command -with the error, e.g. running the stability check on the candidate file. The script will try various -strategies to remove parts of the code. If the output of the command still matches, it will use that -slightly smaller code as starting point for the next iteration, otherwise it will revert and try -a different strategy until all strategies are exhausted. - ## The orphan rules and trait structure For the formatter, we would like to implement `Format` from the rust_formatter crate for all AST diff --git a/crates/ruff_python_formatter/generate.py b/crates/ruff_python_formatter/generate.py index ba52df6e969cf..83ce0415fd632 100755 --- a/crates/ruff_python_formatter/generate.py +++ b/crates/ruff_python_formatter/generate.py @@ -54,13 +54,14 @@ def rustfmt(code: str) -> str: "expr": "expression", "stmt": "statement", "pattern": "pattern", + "type_param": "type_param", "other": "other", } def group_for_node(node: str) -> str: for group in groups: - if node.startswith(group.title()): + if node.startswith(group.title().replace("_", "")): return group else: return "other" @@ -97,7 +98,7 @@ def to_camel_case(node: str) -> str: impl FormatNodeRule<{node}> for Format{node} {{ fn fmt_fields(&self, item: &{node}, f: &mut PyFormatter) -> FormatResult<()> {{ - write!(f, [verbatim_text(item.range)]) + write!(f, [verbatim_text(item)]) }} }} """.strip() # noqa: E501 @@ -111,8 +112,7 @@ def to_camel_case(node: str) -> str: #![allow(unknown_lints, clippy::default_constructed_unit_structs)] use crate::context::PyFormatContext; -use crate::{AsFormat, FormatNodeRule, IntoFormat}; -use ruff_formatter::formatter::Formatter; +use crate::{AsFormat, FormatNodeRule, IntoFormat, PyFormatter}; use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule, FormatResult, FormatRule}; use ruff_python_ast as ast; @@ -126,7 +126,7 @@ def to_camel_case(node: str) -> str: fn fmt( &self, node: &ast::{node}, - f: &mut Formatter>, + f: &mut PyFormatter, ) -> FormatResult<()> {{ FormatNodeRule::::fmt(self, node, f) }} diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py b/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py index 106e97214d577..4a8abc946edc0 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py @@ -1,3 +1,3 @@ # The input source must not contain any Py36-specific syntax (e.g. argument type # annotations, trailing comma after *rest) or this test becomes invalid. -def long_function_name(argument_one, argument_two, argument_three, argument_four, argument_five, argument_six, *rest): ... +def long_function_name(argument_one, argument_two, argument_three, argument_four, argument_five, argument_six, *rest): pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py.expect b/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py.expect index bb26932707899..f63094e472a7b 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py.expect +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_py36.py.expect @@ -9,4 +9,4 @@ def long_function_name( argument_six, *rest, ): - ... + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py b/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py new file mode 100644 index 0000000000000..e843ecf39d89f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py @@ -0,0 +1,194 @@ +A[*b] +A[*b] = 1 +A +del A[*b] +A +A[*b, *b] +A[*b, *b] = 1 +A +del A[*b, *b] +A +A[b, *b] +A[b, *b] = 1 +A +del A[b, *b] +A +A[*b, b] +A[*b, b] = 1 +A +del A[*b, b] +A +A[b, b, *b] +A[b, b, *b] = 1 +A +del A[b, b, *b] +A +A[*b, b, b] +A[*b, b, b] = 1 +A +del A[*b, b, b] +A +A[b, *b, b] +A[b, *b, b] = 1 +A +del A[b, *b, b] +A +A[b, b, *b, b] +A[b, b, *b, b] = 1 +A +del A[b, b, *b, b] +A +A[b, *b, b, b] +A[b, *b, b, b] = 1 +A +del A[b, *b, b, b] +A +A[A[b, *b, b]] +A[A[b, *b, b]] = 1 +A +del A[A[b, *b, b]] +A +A[*A[b, *b, b]] +A[*A[b, *b, b]] = 1 +A +del A[*A[b, *b, b]] +A +A[b, ...] +A[b, ...] = 1 +A +del A[b, ...] +A +A[*A[b, ...]] +A[*A[b, ...]] = 1 +A +del A[*A[b, ...]] +A +l = [1, 2, 3] +A[*l] +A[*l] = 1 +A +del A[*l] +A +A[*l, 4] +A[*l, 4] = 1 +A +del A[*l, 4] +A +A[0, *l] +A[0, *l] = 1 +A +del A[0, *l] +A +A[1:2, *l] +A[1:2, *l] = 1 +A +del A[1:2, *l] +A +repr(A[1:2, *l]) == repr(A[1:2, 1, 2, 3]) +t = (1, 2, 3) +A[*t] +A[*t] = 1 +A +del A[*t] +A +A[*t, 4] +A[*t, 4] = 1 +A +del A[*t, 4] +A +A[0, *t] +A[0, *t] = 1 +A +del A[0, *t] +A +A[1:2, *t] +A[1:2, *t] = 1 +A +del A[1:2, *t] +A +repr(A[1:2, *t]) == repr(A[1:2, 1, 2, 3]) + + +def returns_list(): + return [1, 2, 3] + + +A[returns_list()] +A[returns_list()] = 1 +A +del A[returns_list()] +A +A[returns_list(), 4] +A[returns_list(), 4] = 1 +A +del A[returns_list(), 4] +A +A[*returns_list()] +A[*returns_list()] = 1 +A +del A[*returns_list()] +A +A[*returns_list(), 4] +A[*returns_list(), 4] = 1 +A +del A[*returns_list(), 4] +A +A[0, *returns_list()] +A[0, *returns_list()] = 1 +A +del A[0, *returns_list()] +A +A[*returns_list(), *returns_list()] +A[*returns_list(), *returns_list()] = 1 +A +del A[*returns_list(), *returns_list()] +A +A[1:2, *b] +A[*b, 1:2] +A[1:2, *b, 1:2] +A[*b, 1:2, *b] +A[1:, *b] +A[*b, 1:] +A[1:, *b, 1:] +A[*b, 1:, *b] +A[:1, *b] +A[*b, :1] +A[:1, *b, :1] +A[*b, :1, *b] +A[:, *b] +A[*b, :] +A[:, *b, :] +A[*b, :, *b] +A[a * b()] +A[a * b(), *c, *d(), e * f(g * h)] +A[a * b(), :] +A[a * b(), *c, *d(), e * f(g * h) :] +A[[b] * len(c), :] + + +def f1(*args: *b): + pass + + +f1.__annotations__ + + +def f2(*args: *b, arg1): + pass + + +f2.__annotations__ + + +def f3(*args: *b, arg1: int): + pass + + +f3.__annotations__ + + +def f4(*args: *b, arg1: int = 2): + pass + + +f4.__annotations__ diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py.expect b/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py.expect new file mode 100644 index 0000000000000..e843ecf39d89f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/py_311/pep_646.py.expect @@ -0,0 +1,194 @@ +A[*b] +A[*b] = 1 +A +del A[*b] +A +A[*b, *b] +A[*b, *b] = 1 +A +del A[*b, *b] +A +A[b, *b] +A[b, *b] = 1 +A +del A[b, *b] +A +A[*b, b] +A[*b, b] = 1 +A +del A[*b, b] +A +A[b, b, *b] +A[b, b, *b] = 1 +A +del A[b, b, *b] +A +A[*b, b, b] +A[*b, b, b] = 1 +A +del A[*b, b, b] +A +A[b, *b, b] +A[b, *b, b] = 1 +A +del A[b, *b, b] +A +A[b, b, *b, b] +A[b, b, *b, b] = 1 +A +del A[b, b, *b, b] +A +A[b, *b, b, b] +A[b, *b, b, b] = 1 +A +del A[b, *b, b, b] +A +A[A[b, *b, b]] +A[A[b, *b, b]] = 1 +A +del A[A[b, *b, b]] +A +A[*A[b, *b, b]] +A[*A[b, *b, b]] = 1 +A +del A[*A[b, *b, b]] +A +A[b, ...] +A[b, ...] = 1 +A +del A[b, ...] +A +A[*A[b, ...]] +A[*A[b, ...]] = 1 +A +del A[*A[b, ...]] +A +l = [1, 2, 3] +A[*l] +A[*l] = 1 +A +del A[*l] +A +A[*l, 4] +A[*l, 4] = 1 +A +del A[*l, 4] +A +A[0, *l] +A[0, *l] = 1 +A +del A[0, *l] +A +A[1:2, *l] +A[1:2, *l] = 1 +A +del A[1:2, *l] +A +repr(A[1:2, *l]) == repr(A[1:2, 1, 2, 3]) +t = (1, 2, 3) +A[*t] +A[*t] = 1 +A +del A[*t] +A +A[*t, 4] +A[*t, 4] = 1 +A +del A[*t, 4] +A +A[0, *t] +A[0, *t] = 1 +A +del A[0, *t] +A +A[1:2, *t] +A[1:2, *t] = 1 +A +del A[1:2, *t] +A +repr(A[1:2, *t]) == repr(A[1:2, 1, 2, 3]) + + +def returns_list(): + return [1, 2, 3] + + +A[returns_list()] +A[returns_list()] = 1 +A +del A[returns_list()] +A +A[returns_list(), 4] +A[returns_list(), 4] = 1 +A +del A[returns_list(), 4] +A +A[*returns_list()] +A[*returns_list()] = 1 +A +del A[*returns_list()] +A +A[*returns_list(), 4] +A[*returns_list(), 4] = 1 +A +del A[*returns_list(), 4] +A +A[0, *returns_list()] +A[0, *returns_list()] = 1 +A +del A[0, *returns_list()] +A +A[*returns_list(), *returns_list()] +A[*returns_list(), *returns_list()] = 1 +A +del A[*returns_list(), *returns_list()] +A +A[1:2, *b] +A[*b, 1:2] +A[1:2, *b, 1:2] +A[*b, 1:2, *b] +A[1:, *b] +A[*b, 1:] +A[1:, *b, 1:] +A[*b, 1:, *b] +A[:1, *b] +A[*b, :1] +A[:1, *b, :1] +A[*b, :1, *b] +A[:, *b] +A[*b, :] +A[:, *b, :] +A[*b, :, *b] +A[a * b()] +A[a * b(), *c, *d(), e * f(g * h)] +A[a * b(), :] +A[a * b(), *c, *d(), e * f(g * h) :] +A[[b] * len(c), :] + + +def f1(*args: *b): + pass + + +f1.__annotations__ + + +def f2(*args: *b, arg1): + pass + + +f2.__annotations__ + + +def f3(*args: *b, arg1: int): + pass + + +f3.__annotations__ + + +def f4(*args: *b, arg1: int = 2): + pass + + +f4.__annotations__ diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py b/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py new file mode 100644 index 0000000000000..df005e488ea25 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py @@ -0,0 +1,69 @@ +if (foo := 0): + pass + +if (foo := 1): + pass + +if (y := 5 + 5): + pass + +y = (x := 0) + +y += (x := 0) + +(y := 5 + 5) + +test: int = (test2 := 2) + +a, b = (test := (1, 2)) + +# see also https://github.com/psf/black/issues/2139 +assert (foo := 42 - 12) + +foo(x=(y := f(x))) + + +def foo(answer=(p := 42)): + ... + + +def foo2(answer: (p := 42) = 5): + ... + + +lambda: (x := 1) + +a[(x := 12)] +a[:(x := 13)] + +# we don't touch expressions in f-strings but if we do one day, don't break 'em +f'{(x:=10)}' + + +def a(): + return (x := 3) + await (b := 1) + yield (a := 2) + raise (c := 3) + +def this_is_so_dumb() -> (please := no): + pass + +async def await_the_walrus(): + with (x := y): + pass + + with (x := y) as z, (a := b) as c: + pass + + with (x := await y): + pass + + with (x := await a, y := await b): + pass + + with ((x := await a, y := await b)): + pass + + with (x := await a), (y := await b): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py.expect b/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py.expect new file mode 100644 index 0000000000000..37a6a85087aa4 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py.expect @@ -0,0 +1,71 @@ +if foo := 0: + pass + +if foo := 1: + pass + +if y := 5 + 5: + pass + +y = (x := 0) + +y += (x := 0) + +(y := 5 + 5) + +test: int = (test2 := 2) + +a, b = (test := (1, 2)) + +# see also https://github.com/psf/black/issues/2139 +assert (foo := 42 - 12) + +foo(x=(y := f(x))) + + +def foo(answer=(p := 42)): + ... + + +def foo2(answer: (p := 42) = 5): + ... + + +lambda: (x := 1) + +a[(x := 12)] +a[:(x := 13)] + +# we don't touch expressions in f-strings but if we do one day, don't break 'em +f"{(x:=10)}" + + +def a(): + return (x := 3) + await (b := 1) + yield (a := 2) + raise (c := 3) + + +def this_is_so_dumb() -> (please := no): + pass + + +async def await_the_walrus(): + with (x := y): + pass + + with (x := y) as z, (a := b) as c: + pass + + with (x := await y): + pass + + with (x := await a, y := await b): + pass + + with (x := await a, y := await b): + pass + + with (x := await a), (y := await b): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/import_black_tests.py b/crates/ruff_python_formatter/resources/test/fixtures/import_black_tests.py index 17c99b1185e07..ad45c017847d7 100755 --- a/crates/ruff_python_formatter/resources/test/fixtures/import_black_tests.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/import_black_tests.py @@ -43,6 +43,7 @@ def import_fixture(fixture: Path, fixture_set: str): # The name of the folders in the `data` for which the tests should be imported FIXTURE_SETS = [ + "fast", "py_36", "py_37", "py_38", @@ -58,9 +59,6 @@ def import_fixture(fixture: Path, fixture_set: str): # Tests that ruff doesn't fully support yet and, therefore, should not be imported IGNORE_LIST = [ - "pep_572_remove_parens.py", # Reformatting bugs - "pep_646.py", # Rust Python parser bug - # Contain syntax errors "async_as_identifier.py", "invalid_header.py", diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/.editorconfig b/crates/ruff_python_formatter/resources/test/fixtures/ruff/.editorconfig new file mode 100644 index 0000000000000..ddc5dc593f499 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/.editorconfig @@ -0,0 +1,3 @@ +[mixed_space_and_tab.py] +generated_code = true +ij_formatter_enabled = false \ No newline at end of file diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.options.json b/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.options.json new file mode 100644 index 0000000000000..4a3e3c6dd752f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.options.json @@ -0,0 +1,15 @@ +[ + { + "indent_style": { + "Space": 4 + } + }, + { + "indent_style": { + "Space": 2 + } + }, + { + "indent_style": "Tab" + } +] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.py new file mode 100644 index 0000000000000..60c655f686e97 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.py @@ -0,0 +1,102 @@ +def single_line_backslashes1(): + """ content\ """ + return + + +def single_line_backslashes2(): + """ content\\ """ + return + + +def single_line_backslashes3(): + """ content\\\ """ + return + + +def multiline_backslashes1(): + """This is a docstring with + some lines of text\ """ + return + + +def multiline_backslashes2(): + """This is a docstring with + some lines of text\\ """ + return + + +def multiline_backslashes3(): + """This is a docstring with + some lines of text\\\ """ + return + + +def multiple_negatively_indented_docstring_lines(): + """a + b + c + d + e + """ + + +def overindentend_docstring(): + """a + over-indented + """ + + +def comment_before_docstring(): + # don't lose this function comment ... + """Does nothing. + + But it has comments + """ # ... neither lose this function comment + + +class CommentBeforeDocstring(): + # don't lose this class comment ... + """Empty class. + + But it has comments + """ # ... neither lose this class comment + + +class IndentMeSome: + def doc_string_without_linebreak_after_colon(self): """ This is somewhat strange + a + b + We format this a is the docstring had started properly indented on the next + line if the target indentation. This may we incorrect since source and target + indentation can be incorrect, but this is also an edge case. + """ + + +class IgnoreImplicitlyConcatenatedStrings: + """""" "" + + +def docstring_that_ends_with_quote_and_a_line_break1(): + """ + he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break2(): + """he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break3(): + """he said "the news of my death have been greatly exaggerated" + + """ + + +class TabbedIndent: + def tabbed_indent(self): + """check for correct tabbed formatting + ^^^^^^^^^^ + Normal indented line + - autor + """ diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py index e6cb4b0ac5a01..0219429b29dc0 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py @@ -106,4 +106,22 @@ a.b ) +# regression: https://github.com/astral-sh/ruff/issues/6181 +(# +()).a +( + ( + a # trailing end-of-line + # trailing own-line + ) # dangling before dot end-of-line + .b # trailing end-of-line +) + +( + ( + a + ) + # dangling before dot own-line + .b +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/binary.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/binary.py index 30cf4c4465f47..572518635ea86 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/binary.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/binary.py @@ -211,3 +211,14 @@ log(self.price / self.strike) + (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time ) / self.sigmaT + +# Stability with end-of-line comments between empty tuples and bin op +x = () - (# +) +x = ( + () + - () # +) +x = ( + () - () # +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/boolean_operation.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/boolean_operation.py index f976491cd1a42..16391cdf50947 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/boolean_operation.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/boolean_operation.py @@ -62,3 +62,35 @@ and [dddddddddddddd, eeeeeeeeee, fffffffffffffff] ): pass + +# Regression test for https://github.com/astral-sh/ruff/issues/6068 +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or numpy and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and numpy or isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy or isinstance(ccccccccccc, dddddd) +): + pass + + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or (xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy) and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and (xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy) or isinstance(ccccccccccc, dddddd) +): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/call.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/call.py index 8c372180ce7f5..5dc7d1af44309 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/call.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/call.py @@ -52,7 +52,7 @@ def f(*args, **kwargs): hey_this_is_a_very_long_call=1, it_has_funny_attributes_asdf_asdf=1, too_long_for_the_line=1, really=True ) -# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +# Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) result = ( session.query(models.Customer.id) .filter( @@ -86,3 +86,122 @@ def f(*args, **kwargs): f( a.very_long_function_function_that_is_so_long_that_it_expands_the_parent_but_its_only_a_single_argument() ) + +f( # abc +) + +f( # abc + # abc +) + +f( + # abc +) + +f ( # abc + 1 +) + +f ( + # abc + 1 +) + +f ( + 1 + # abc +) + +threshold_date = datetime.datetime.now() - datetime.timedelta( # comment + days=threshold_days_threshold_days +) + +# Parenthesized and opening-parenthesis comments +func( + (x for x in y) +) + +func( # outer comment + (x for x in y) +) + +func( + ( # inner comment + x for x in y + ) +) + +func( + ( + # inner comment + x for x in y + ) +) + +func( # outer comment + ( # inner comment + 1 + ) +) + +func( + # outer comment + ( # inner comment + x for x in y + ) +) + + +func( + ( # inner comment + [] + ) +) + +func( + # outer comment + ( # inner comment + [] + ) +) + +# Comments between the function and its arguments +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # baz + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + (foo # awkward comment + ) + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + ) + () + .bbbbbbbbbbbbbbbb +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/compare.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/compare.py index 906d5710aa333..88b6da20bd861 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/compare.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/compare.py @@ -59,3 +59,55 @@ >= c ) ] + +def f(): + return ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKC", s2).casefold() + ) + +# Call expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = aaaaaaaaaaact_id == self.get_content_type( + obj=rel_obj, using=instance._state.db +) + +# Call expressions with trailing subscripts. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +# Subscripts expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/dict_comp.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/dict_comp.py index cf4df74d92bba..2f6f9a3c48878 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/dict_comp.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/dict_comp.py @@ -86,3 +86,26 @@ k: str(v) for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values } + +{ + k: v + for ( # foo + + x, aaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaay) in z +} + +a = { + k: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +a = { + k: [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +aaaaaaaaaaaaaaaaaaaaa = { + k: o for o in self.registry.values if o.__class__ is not ModelAdmin +} diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py new file mode 100644 index 0000000000000..a60efa1cddfa8 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py @@ -0,0 +1,35 @@ +( + f'{one}' + f'{two}' +) + + +rf"Not-so-tricky \"quote" + +# Regression test for fstrings dropping comments +result_f = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + # XXX: The following line changes depending on whether the tests + # are run through the interactive interpreter or with -m + # It also varies depending on the platform (stack size) + # Fortunately, we don't care about exactness here, so we use regex + r' \[Previous line repeated (\d+) more times\]' '\n' + 'RecursionError: maximum recursion depth exceeded\n' +) + + +# Regression for fstring dropping comments that were accidentally attached to +# an expression inside a formatted value +( + f'{1}' + # comment + '' +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/generator_exp.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/generator_exp.py index f586dcd7fb373..7baf9602e73aa 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/generator_exp.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/generator_exp.py @@ -25,3 +25,25 @@ # trailing ) ) + +len( + # leading + a for b in c + # trailing +) + +a = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +a = ( + [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +aaaaaaaaaaaaaaaaaaaaa = ( + o for o in self.registry.values if o.__class__ is not ModelAdmin +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py deleted file mode 100644 index 8b6af32d0b587..0000000000000 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py +++ /dev/null @@ -1,7 +0,0 @@ -( - f'{one}' - f'{two}' -) - - -rf"Not-so-tricky \"quote" diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py index a52616daae8f8..32a57bed4a24b 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py @@ -56,12 +56,16 @@ z) # Trailing # Trailing - a = ( lambda # Dangling : 1 ) +a = ( + lambda x # Dangling + , y: 1 +) + # Regression test: lambda empty arguments ranges were too long, leading to unstable # formatting (lambda:(# @@ -75,3 +79,42 @@ def f( # ...but we do preserve a trailing comma after the arguments a = lambda b,: 0 + +lambda a,: 0 +lambda *args,: 0 +lambda **kwds,: 0 +lambda a, *args,: 0 +lambda a, **kwds,: 0 +lambda *args, b,: 0 +lambda *, b,: 0 +lambda *args, **kwds,: 0 +lambda a, *args, b,: 0 +lambda a, *, b,: 0 +lambda a, *args, **kwds,: 0 +lambda *args, b, **kwds,: 0 +lambda *, b, **kwds,: 0 +lambda a, *args, b, **kwds,: 0 +lambda a, *, b, **kwds,: 0 +lambda a, /: a +lambda a, /, c: a + +# Dangling comments without parameters. +( + lambda + : # 3 + None +) + +( + lambda + # 3 + : None +) + +( + lambda # 1 + # 2 + : # 3 + # 4 + None # 5 +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list.py index f0fedc6957da1..71ac00e99c8bb 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list.py @@ -21,3 +21,40 @@ aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa ] + +# Comment placement in non-empty lists +c1 = [ # trailing open bracket + # leading item + 1, + + # between + + 2, # trailing item + # leading close bracket +] # trailing close bracket + + +[ # end-of-line comment +] + +[ # end-of-line comment + # own-line comment +] + +[ # end-of-line comment + 1 +] + +[ # inner comment + first, + second, + third +] # outer comment + +[ # inner comment + # own-line comment + ( # end-of-line comment + # own-line comment + first, + ), +] # outer comment diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list_comp.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list_comp.py index d0cf86ea2ffce..21f89cb019613 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list_comp.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/list_comp.py @@ -56,4 +56,20 @@ # Tuples with BinOp [i for i in (aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc)] -[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b] \ No newline at end of file +[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b] + +a = [ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +a = [ + [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +aaaaaaaaaaaaaaaaaaaaa = [ + o for o in self.registry.values if o.__class__ is not ModelAdmin +] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/named_expr.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/named_expr.py index 15ac1c75775ee..0d9b8e366cae0 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/named_expr.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/named_expr.py @@ -8,6 +8,52 @@ ): pass +if ( + # 1 + x # 2 + := # 3 + (y) # 4 +): + pass + +if ( + # 1 + x # 2 + := # 3 + (y) # 4 + # 5 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + y # 4 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + ( # 4 + y # 5 + ) # 6 +): + pass + +if ( + x # 2 + := # 3 + y +): + pass + y0 = (y1 := f(x)) f(x:=y, z=True) @@ -36,3 +82,18 @@ def f(): (x := 1) (x := 1) + (y := 2) + +with (x := 1): + pass + + +def f(): + yield (x := 1) + + +def f(): + yield from (x := 1) + + +async def f(): + await (x := 1) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/split_empty_brackets.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/split_empty_brackets.py new file mode 100644 index 0000000000000..309d0cdfd50f8 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/split_empty_brackets.py @@ -0,0 +1,90 @@ +# Expressions with empty parentheses. +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(1) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(0) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold(1) +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(1) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold(1) +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold( + # foo + ) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold( + # foo + ) +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [1].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [1].unicodedata.normalize("NFKC", s1).casefold() + == [].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [1].unicodedata.normalize("NFKC", s1).casefold() + == [1].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {1}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {1}.unicodedata.normalize("NFKC", s1).casefold() + == {}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {1}.unicodedata.normalize("NFKC", s1).casefold() + == {1}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + ([]).unicodedata.normalize("NFKC", s1).casefold() + == ([]).unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +return await self.http_client.fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +return await self.http_client().fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +return await self().http_client().fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +response = await sync_to_async( + lambda: self.django_handler.get_response(request), thread_sensitive=True +)() diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/starred.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/starred.py index 437b011b71179..cdbcf4c942358 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/starred.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/starred.py @@ -13,3 +13,21 @@ [What, i, this, s, very, long, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] ) # trailing value comment ) + +call( + x, + # Leading starred comment + * # Trailing star comment + [ + # Leading value comment + [What, i, this, s, very, long, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + ] # trailing value comment +) + +call( + x, + * # Trailing star comment + ( # Leading value comment + y + ) +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py index 78e215f91ada6..1e45d1abf1a19 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py @@ -124,3 +124,9 @@ 'c' ) } + + +# Regression test for https://github.com/astral-sh/ruff/issues/5893 +x = ("""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") +x = (f"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" f"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") +x = (b"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" b"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/tuple.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/tuple.py index 13859fb27d3e2..9c6c5a6d5b113 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/tuple.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/tuple.py @@ -3,6 +3,8 @@ a2 = (1, 2) a3 = (1, 2), 3 a4 = ((1, 2), 3) +a5 = (1), (2) +a6 = ((1), (2)) # Wrapping parentheses checks b1 = (("Michael", "Ende"), ("Der", "satanarchäolügenialkohöllische", "Wunschpunsch"), ("Beelzebub", "Irrwitzer"), ("Tyrannja", "Vamperl"),) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unary.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unary.py index 11106d7d2396a..9b08dc9baaa36 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unary.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unary.py @@ -140,3 +140,9 @@ # Regression: https://github.com/astral-sh/ruff/issues/5338 if a and not aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ... + +if ( + not + # comment + a): + ... diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unsplittable.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unsplittable.py new file mode 100644 index 0000000000000..85545d6ac0dd6 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unsplittable.py @@ -0,0 +1,72 @@ +x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +x_aa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +xxxxx = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +while ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + pass + +while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + pass + +# Only applies in `Parenthesize::IfBreaks` positions +raise aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +raise ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) + +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Can never apply on expression statement level +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Is it only relevant for items that can't break + +aaaaaaa = 111111111111111111111111111111111111111111111111111111111111111111111111111111 +aaaaaaa = ( + 1111111111111111111111111111111111111111111111111111111111111111111111111111111 +) + +aaaaaaa = """111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" + +# Never parenthesize multiline strings +aaaaaaa = ( + """1111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" +) + + + +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbb +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + +for converter in connection.ops.get_db_converters( + expression +) + expression.get_db_converters(connection): + ... + + +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # awkward comment +) + +def test(): + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person, blank=True) + + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyFieldAttributeChainField + +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person, blank=True) +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyFieldAttributeChainFieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeld + +def test(): + if True: + VLM_m2m = VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through + allows_group_by_select_index = self.connection.features.allows_group_by_select_index diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/yield.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/yield.py index 592cebdaa1c57..0959855cf53bd 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/yield.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/yield.py @@ -57,3 +57,50 @@ def foo(): yield from (yield l) + ( + yield + #comment 1 + * # comment 2 + # comment 3 + test, # comment 4 + 1 + ) + + yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" + ) + + yield aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +yield ("Cache key will cause errors if used with memcached: %r " "(longer than %s)" % ( + key, + MEMCACHE_MAX_KEY_LENGTH, +) + ) + +yield "Cache key will cause errors if used with memcached: %r " "(longer than %s)" % ( + key, + MEMCACHE_MAX_KEY_LENGTH, +) + + +yield ("Unnecessary") + + +yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" +) +yield ( + "# * Remove `managed = False` lines if you wish to allow " + "Django to create, modify, and delete the table" +) +yield ( + "# Feel free to rename the models, but don't rename db_table values or " + "field names." +) + +yield "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " "to the desired behavior" +yield "# * Remove `managed = False` lines if you wish to allow " "Django to create, modify, and delete the table" +yield "# Feel free to rename the models, but don't rename db_table values or " "field names." diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/comments.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/comments.py new file mode 100644 index 0000000000000..ede6493669a51 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/comments.py @@ -0,0 +1,28 @@ +pass + +# fmt: off + # A comment that falls into the verbatim range +a + b # a trailing comment + +# in between comments + +# function comment +def test(): + pass + + # under indent + + def nested(): + ... + + # trailing comment that falls into the verbatim range + # trailing outer comment + # fmt: on + +a + b + +def test(): + pass + # fmt: off + # a trailing comment + diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/empty_file.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/empty_file.py new file mode 100644 index 0000000000000..c61bb37fe0637 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/empty_file.py @@ -0,0 +1,5 @@ +# fmt: off + + # this does not work because there are no statements + +# fmt: on diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.options.json b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.options.json new file mode 100644 index 0000000000000..e662f7287986d --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.options.json @@ -0,0 +1,8 @@ +[ + { + "indent_style": { "Space": 4 } + }, + { + "indent_style": { "Space": 2 } + } +] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.py new file mode 100644 index 0000000000000..c387829010ebb --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.py @@ -0,0 +1,19 @@ +def test(): + # fmt: off + """ This docstring does not + get formatted + """ + + # fmt: on + + but + this + does + +def test(): + # fmt: off + # just for fun + # fmt: on + # leading comment + """ This docstring gets formatted + """ # trailing comment + + and_this + gets + formatted + too diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/form_feed.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/form_feed.py new file mode 100644 index 0000000000000..e5efe750eb4ec --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/form_feed.py @@ -0,0 +1,7 @@ +# fmt: off +# DB layer (form feed at the start of the next line) + +# fmt: on + +def test(): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.options.json b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.options.json new file mode 100644 index 0000000000000..8f229d10a5f88 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.options.json @@ -0,0 +1,11 @@ +[ + { + "indent_style": { "Space": 4 } + }, + { + "indent_style": { "Space": 1 } + }, + { + "indent_style": "Tab" + } +] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.py new file mode 100644 index 0000000000000..c0cb6c1849b05 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.py @@ -0,0 +1,55 @@ +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + pass + more + # fmt: on + + formatted + + def test(): + a_small_indent + # fmt: off +# fix under-indented comments + (or_the_inner_expression + +expressions + ) + + if True: + pass + # fmt: on + + +# fmt: off +def test(): + pass + + # It is necessary to indent comments because the following fmt: on comment because it otherwise becomes a trailing comment + # of the `test` function if the "proper" indentation is larger than 2 spaces. + # fmt: on + +disabled + formatting; + +# fmt: on + +formatted; + +def test(): + pass + # fmt: off + """A multiline strings + that should not get formatted""" + + "A single quoted multiline \ + string" + + disabled + formatting; + +# fmt: on + +formatted; diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/last_statement.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/last_statement.py new file mode 100644 index 0000000000000..1fa2cee40aae5 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/last_statement.py @@ -0,0 +1,10 @@ +def test(): + # fmt: off + + a + b + + + + # suppressed comments + +a + b # formatted diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.options.json b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.options.json new file mode 100644 index 0000000000000..e40788162c1b9 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.options.json @@ -0,0 +1,11 @@ +[ + { + "indent_style": { "Space": 4 } + }, + { + "indent_style": { "Space": 2 } + }, + { + "indent_style": "Tab" + } +] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.py new file mode 100644 index 0000000000000..0cf93824c1dc4 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.py @@ -0,0 +1,15 @@ +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: +# Fun tab, space, tab, space. Followed by space, tab, tab, space + pass + more + else: + other + # fmt: on + diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/no_fmt_on.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/no_fmt_on.py new file mode 100644 index 0000000000000..d2955856e3a8c --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/no_fmt_on.py @@ -0,0 +1,9 @@ +def test(): + # fmt: off + not formatted + + if unformatted + a: + pass + +# Get's formatted again +a + b diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/off_on_off_on.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/off_on_off_on.py new file mode 100644 index 0000000000000..7bc6ca8b467f8 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/off_on_off_on.py @@ -0,0 +1,71 @@ +# Tricky sequences of fmt off and on + +# Formatted +a + b + +# fmt: off + # not formatted 1 +# fmt: on +a + b + # formatted + + +# fmt: off + # not formatted 1 +# fmt: on + # not formatted 2 +# fmt: off +a + b +# fmt: on + + +# fmt: off + # not formatted 1 +# fmt: on + # formatted 1 +# fmt: off + # not formatted 2 +a + b +# fmt: on + # formatted +b + c + + +# fmt: off +a + b + + # not formatted +# fmt: on + # formatted +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on + # formatted +# fmt: off + # not formatted 2 +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on + # formatted + +# leading +a + b +# fmt: off + + # leading unformatted +def test (): + pass + + # fmt: on + +a + b diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/simple.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/simple.py new file mode 100644 index 0000000000000..dfe64b1c2e66f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/simple.py @@ -0,0 +1,9 @@ +# Get's formatted +a + b + +# fmt: off +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/trailing_comments.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/trailing_comments.py new file mode 100644 index 0000000000000..4ddb4ad8a6e37 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/trailing_comments.py @@ -0,0 +1,40 @@ +a = 10 +# fmt: off + +# more format + +def test(): ... + + +# fmt: on + +b = 20 +# Sequence of trailing comments that toggle between format on and off. The sequence ends with a `fmt: on`, so that the function gets formatted. +# formatted 1 +# fmt: off + # not formatted +# fmt: on + # formatted comment +# fmt: off + # not formatted 2 +# fmt: on + + # formatted +def test2 (): + ... + +a = 10 + +# Sequence of trailing comments that toggles between format on and off. The sequence ends with a `fmt: off`, so that the function is not formatted. + # formatted 1 +# fmt: off + # not formatted +# fmt: on + # formattd +# fmt: off + + # not formatted +def test3 (): + ... + +# fmt: on diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/yapf.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/yapf.py new file mode 100644 index 0000000000000..741ca7213a9a4 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/yapf.py @@ -0,0 +1,17 @@ +# Get's formatted +a + b + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# yapf: enable + +# Get's formatted again +a + b + + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py new file mode 100644 index 0000000000000..98e3bedc6b94f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py @@ -0,0 +1,19 @@ + +@FormattedDecorator(a =b) + # leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip + # leading class comment +class Test: + pass + + + +@FormattedDecorator(a =b) +# leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip +# leading class comment +def test(): + pass + diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py new file mode 100644 index 0000000000000..2f8bdcef3bd0b --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py @@ -0,0 +1,13 @@ +def test(): + # leading comment + """ This docstring does not + get formatted + """ # fmt: skip + # trailing comment + +def test(): + # leading comment + """ This docstring gets formatted + """ # trailing comment + + and_this + gets + formatted + too diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/match.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/match.py new file mode 100644 index 0000000000000..0ff31d43836ad --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/match.py @@ -0,0 +1,73 @@ +def http_error(status): + match status : # fmt: skip + case 400 : # fmt: skip + return "Bad request" + case 404: + return "Not found" + case 418: + return "I'm a teapot" + case _: + return "Something's wrong with the internet" + +# point is an (x, y) tuple +match point: + case (0, 0): # fmt: skip + print("Origin") + case (0, y): + print(f"Y={y}") + case (x, 0): + print(f"X={x}") + case (x, y): + print(f"X={x}, Y={y}") + case _: + raise ValueError("Not a point") + +class Point: + x: int + y: int + +def location(point): + match point: + case Point(x=0, y =0 ) : # fmt: skip + print("Origin is the point's location.") + case Point(x=0, y=y): + print(f"Y={y} and the point is on the y-axis.") + case Point(x=x, y=0): + print(f"X={x} and the point is on the x-axis.") + case Point(): + print("The point is located somewhere else on the plane.") + case _: + print("Not a point") + + +match points: + case []: + print("No points in the list.") + case [ + Point(0, 0) + ]: # fmt: skip + print("The origin is the only point in the list.") + case [Point(x, y)]: + print(f"A single point {x}, {y} is in the list.") + case [Point(0, y1), Point(0, y2)]: + print(f"Two points on the Y axis at {y1}, {y2} are in the list.") + case _: + print("Something else is found in the list.") + + +match test_variable: + case ( + 'warning', + code, + 40 + ): # fmt: skip + print("A warning has been received.") + case ('error', code, _): + print(f"An error {code} occurred.") + + +match point: + case Point(x, y) if x == y: # fmt: skip + print(f"The point is located on the diagonal Y=X at {x}.") + case Point(x, y): + print(f"Point is not on the diagonal.") diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/or_else.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/or_else.py new file mode 100644 index 0000000000000..c2dccee81e547 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/or_else.py @@ -0,0 +1,31 @@ +for item in container: + if search_something(item): + # Found it! + process(item) + break + # leading comment +else : #fmt: skip + # Didn't find anything.. + not_found_in_container() + + +while i < 10: + print(i) + +# leading comment +else : #fmt: skip + # Didn't find anything.. + print("I was already larger than 9") + + +try : # fmt: skip + some_call() +except Exception : # fmt: skip + pass +except : # fmt: skip + handle_exception() + +else : # fmt: skip + pass +finally : # fmt: skip + finally_call() diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/parentheses.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/parentheses.py new file mode 100644 index 0000000000000..7533f56a1eb37 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/parentheses.py @@ -0,0 +1,20 @@ +if ( + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 # trailing condition comment + # trailing own line comment +): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and ((((y)))): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and y: # fmt: skip + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/type_params.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/type_params.py new file mode 100644 index 0000000000000..50aba6ad8ec51 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/type_params.py @@ -0,0 +1,38 @@ +class TestTypeParam[ T ]: # fmt: skip + pass + +class TestTypeParam [ # trailing open paren comment + # leading comment + T # trailing type param comment + # trailing type param own line comment +]: # fmt: skip + pass + +class TestTrailingComment4[ + T +] ( # trailing arguments open parenthesis comment + # leading argument comment + A # trailing argument comment + # trailing argument own line comment +): # fmt: skip + pass + +def test [ + # comment + A, + + # another + + B, +] (): # fmt: skip + ... + +def test [ + # comment + A, + + # another + + B, +] () -> str: # fmt: skip + ... diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/call_chains.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/call_chains.py new file mode 100644 index 0000000000000..c5d806e27e082 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/call_chains.py @@ -0,0 +1,163 @@ +# Test cases for call chains and optional parentheses, with and without fluent style + +raise OsError("") from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a(aaaa) + +raise OsError( + "sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll" +) from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a( + aaaa +) + +a1 = Blog.objects.filter(entry__headline__contains="Lennon").filter( + entry__pub_date__year=2008 +) + +a2 = Blog.objects.filter( + entry__headline__contains="Lennon", +).filter( + entry__pub_date__year=2008, +) + +raise OsError("") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +raise OsError("sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +# Break only after calls and indexing +b1 = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ) + .count() +) + +b2 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .limit_results[:10] + .filter( + entry__pub_date__month=10, + ) +) + +# Nested call chains +c1 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ).filter( + entry__pub_date__year=2008, + ) + + Blog.objects.filter( + entry__headline__contains="McCartney", + ) + .limit_results[:10] + .filter( + entry__pub_date__year=2010, + ) +).all() + +# Test different cases with trailing end of line comments: +# * fluent style, fits: no parentheses -> ignore the expand_parent +# * fluent style, doesn't fit: break all soft line breaks +# * default, fits: no parentheses +# * default, doesn't fit: parentheses but no soft line breaks + +# Fits, either style +d11 = x.e().e().e() # +d12 = (x.e().e().e()) # +d13 = ( + x.e() # + .e() + .e() +) + +# Doesn't fit, default +d2 = ( + x.e().esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdddd() # +) + +# Doesn't fit, fluent style +d3 = ( + x.e() # + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() +) + +# Don't drop the bin op parentheses +e1 = (1 + 2).w().t() +e2 = (1 + 2)().w().t() +e3 = (1 + 2)[1].w().t() + +# Treat preserved parentheses correctly +f1 = (b().c()).d(1,) +f2 = b().c().d(1,) +f3 = (b).c().d(1,) +f4 = (a)(b).c(1,) +f5 = (a.b()).c(1,) + +# Indent in the parentheses without breaking +g1 = ( + queryset.distinct().order_by(field.name).values_list(field_name_flat_long_long=True) +) + +# Fluent style in subexpressions +if ( + not a() + .b() + .cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc() +): + pass +h2 = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + ccccccccccccccccccccccccc() + .dddddddddddddddddddddd() + .eeeeeeeeee() + .ffffffffffffffffffffff() +) + +# Parentheses aren't allowed on statement level, don't use fluent style here +if True: + (alias).filter(content_typeold_content_type).update( + content_typenew_contesadfasfdant_type + ) + +zero( + one, +).two( + three, +).four( + five, +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id() +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/nested.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/nested.py new file mode 100644 index 0000000000000..dbe1a487e9816 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/nested.py @@ -0,0 +1,53 @@ +a1 = f( # 1 + g( # 2 + ) +) +a2 = f( # 1 + g( # 2 + x + ) +) +a3 = f( + ( + # + () + ) +) + + +call( + a, + b, + [ # Empty because of + ] +) + +a = a + b + c + d + ( # Hello + e + f + g +) + +a = int( # type: ignore + int( # type: ignore + int( # type: ignore + 6 + ) + ) +) + +# Stability and correctness checks +b1 = () - ( # +) +() - ( # +) +b2 = () - f( # +) +() - f( # +) +b3 = ( + # + () +) +( + # + () +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_empty.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_empty.py new file mode 100644 index 0000000000000..68c76585bb825 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_empty.py @@ -0,0 +1,86 @@ +# Opening parentheses end-of-line comment without a value in the parentheses + +( # a 1 +) +a2 = ( # a 2 +) +a3 = f( # a 3 +) +a4 = ( # a 4 +) = a4 +a5: List( # a 5 +) = 5 + +raise ( # b 1a +) +raise b1b from ( # b 1b +) +raise ( # b 1c +) from b1c +del ( # b 2 +) +assert ( # b 3 +), ( #b 4 +) + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + ) + yield ( # c 2 + ) +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + ) + +with ( # d 1 +): pass +match ( # d 2 +): + case d2: + pass +match d3: + case ( # d 3 + ): + pass +while ( # d 4 +): + pass +if ( # d 5 +): + pass +elif ( # d 6 +): + pass +for ( # d 7 +) in ( # d 8 +): + pass +try: + pass +except ( # d 9 +): + pass + + +def e1( # e 1 +): pass + + +def e2() -> ( # e 2 +): pass + + +class E3( # e 3 +): pass + + +f1 = [ # f 1 +] +[ # f 2 +] +f3 = { # f3 +} +{ # f 4 +} diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_value.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_value.py new file mode 100644 index 0000000000000..2774504d6a904 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_value.py @@ -0,0 +1,150 @@ +# Opening parentheses end-of-line comment with value in the parentheses + +( # a 1 +x) +a2 = ( # a 2 +x) +a3 = f( # a 3 +x) +a4 = ( # a 4 +x) = a4 +a5: List( # a 5 +x) = 5 + +raise ( # b 1a +x) +raise b1b from ( # b 1b +x) +raise ( # b 1c +x) from b1c +del ( # b 2 +x) +assert ( # b 3 +x), ( #b 4 +x) + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + x) + yield ( # c 2 + x) +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + x) + +with ( # d 1 +x): pass +match ( # d 2 +x): + case d2: + pass +match d3: + case ( # d 3 + x): + pass +while ( # d 4 +x): + pass +if ( # d 5 +x): + pass +elif ( # d 6 +y): + pass +for ( # d 7 +x) in ( # d 8 +y): + pass +try: + pass +except ( # d 9 + x +): + pass + + +def e1( # e 1 +x): pass + + +def e2() -> ( # e 2 +x): pass + + +def e3() -> ( + # e 2 +x): pass + + +def e4() -> ( + x +# e 4 +): pass + + +def e5() -> ( # e 5 + ( # e 5 + x + ) +): pass + + +def e6() -> ( + ( + # e 6 + x + ) +): pass + + +def e7() -> ( + ( + x + # e 7 + ) +): pass + + +def e8() -> ( + ( + x + ) + # e 8 +): pass + + +class E9( # e 9 +x): pass + + +f1 = [ # f 1 +x] +[ # f 2 +x] +f3 = { # f3 +x} +{ # f 4 +x} + + + +# Non-empty parentheses: These are not allowed without a value +def f1[ # f1 + T +](): pass +f2 = ( # f2 + i for i in range(10) +) +f3 = [ # f3 + i for i in range(10) +] +f4 = { # f4 + i for i in range(10) +} +f5 = { # f5 + i: i**2 for i in range(10) +} + + diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/skip_magic_trailing_comma.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/skip_magic_trailing_comma.py index b91681ace8a4b..594f1feed1b50 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/skip_magic_trailing_comma.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/skip_magic_trailing_comma.py @@ -27,3 +27,7 @@ def g(a,): pass x1 = lambda y: 1 x2 = lambda y,: 1 + +# Ignore trailing comma. +with (a,): # magic trailing comma + ... diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assert.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assert.py index 8f12d268b0e5a..b5ef028af1450 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assert.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assert.py @@ -12,7 +12,7 @@ assert ( # Leading test value True # Trailing test value same-line - # Trailing test value own-line + # Trailing test value own-line ), "Some string" # Trailing msg same-line # Trailing assert @@ -23,8 +23,133 @@ assert ( # Leading test value True # Trailing test value same-line - # Trailing test value own-line + # Trailing test value own-line # Test dangler ), "Some string" # Trailing msg same-line # Trailing assert + +def test(): + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, ( + "Not what we expected and the message is too long to fit ineeeeee one line" + ) + + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, ( + "Not what we expected and the message is too long to fit in one lineeeee" + ) + + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee" + + assert expected == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + }, "Not what we expected and the message is too long to fit ineeeeee one line" + + assert expected == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + }, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee" diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assign.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assign.py index a0317eac9a41b..8ccd5b008d017 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assign.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assign.py @@ -13,6 +13,44 @@ bakjdshflkjahdslkfjlasfdahjlfds ] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] +aa = [ + +] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = [ + # foo +] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = ([ +]) = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + aaaa = ( # trailing # comment bbbbb) = cccccccccccccccc = 3 + +x = ( # comment + [ # comment + a, + b, + c, + ] +) = 1 + + +x = ( + # comment + [ + a, + b, + c, + ] +) = 1 + + +x = ( + [ # comment + a, + b, + c, + ] +) = 1 diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/class_definition.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/class_definition.py index 7481a071f53e3..442441465e941 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/class_definition.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/class_definition.py @@ -43,3 +43,166 @@ class TestTrailingComment2: # trailing comment pass +class TestTrailingComment3[T]: # trailing comment + pass + + +class TestTrailingComment4[T](A): # trailing comment + pass + + +class Test: + """Docstring""" + + +class Test: + # comment + """Docstring""" + + +class Test: + """Docstring""" + x = 1 + + +class Test: + """Docstring""" + # comment + x = 1 + + +class Test: + + """Docstring""" + + +class Test: + # comment + + """Docstring""" + + +class Test: + + # comment + + """Docstring""" + + +class Test: + + """Docstring""" + x = 1 + + +class Test: + + """Docstring""" + # comment + x = 1 + + +class C(): # comment + pass + + +class C( # comment +): + pass + + +class C( + # comment +): + pass + + +class C(): # comment + pass + + +class C( # comment + # comment + 1 +): + pass + + +class C( + 1 + # comment +): + pass + + +@dataclass +# Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +class AltCLIPOutput(ModelOutput): + ... + + +@dataclass +class AltCLIPOutput( # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +): + ... + + +@dataclass +class AltCLIPOutput( + # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +): + ... + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, Cccccccccccccccccccccc]: + pass + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, *Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, **Cccccccccccccccccccccc]: + pass + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[*Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[**Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[**P, *Ts, T]: + pass + + +class TestTypeParams[ # trailing bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +]: + pass + + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](B, C, D): + pass + + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, Cccccccccccccccccccccccc, Ddddddddddddddddddddddddd): + pass + + + +class TestTypeParams[A, B, C](meta=Aaaaaaaaaaaaaaaaaaaaaa): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/delete.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/delete.py index c8ca7da9d70e1..a86c65dde8f04 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/delete.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/delete.py @@ -73,3 +73,7 @@ del ( # dangling end of line comment ) + +del ( # dangling end of line comment + # dangling own line comment +) # trailing statement comment diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ellipsis.pyi b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ellipsis.pyi new file mode 100644 index 0000000000000..499ef0aacc0c7 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ellipsis.pyi @@ -0,0 +1,102 @@ +"""Compound statements with no body should be written on one line.""" + +if True: + ... +elif True: + ... +else: + ... + +if True: + # comment + ... +elif True: + # comment + ... +else: + # comment + ... + +if True: + ... # comment +elif True: + ... # comment +else: + ... # comment + +for i in []: + ... +else: + ... + +for i in []: + # comment + ... +else: + # comment + ... + +for i in []: + ... # comment +else: + ... # comment + +while True: + ... +else: + ... + +while True: + # comment + ... +else: + # comment + ... + +while True: + ... # comment +else: + ... # comment + +with True: + ... + +with True: + # comment + ... + +with True: + ... # comment + +match x: + case 1: + ... + case 2: + # comment + ... + case 3: + ... # comment + +try: + ... +except: + ... +finally: + ... + +try: + # comment + ... +except: + # comment + ... +finally: + # comment + ... + +try: + ... # comment +except: + ... # comment +finally: + ... # comment \ No newline at end of file diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/for.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/for.py index 3a96b5390f3fc..868db10fc6ed7 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/for.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/for.py @@ -32,3 +32,41 @@ # type comment for x in (): # type: int ... + +# Tuple parentheses for iterable. +for x in 1, 2, 3: + pass + +for x in (1, 2, 3): + pass + +for x in 1, 2, 3,: + pass + +# Don't keep parentheses around right target if it can made fit by breaking sub expressions +for column_name, ( + referenced_column_name, + referenced_table_name, +) in relations.items(): + pass + +for column_name, [ + referenced_column_name, + referenced_table_name, +] in relations.items(): + pass + +for column_name, [ + referenced_column_name, + referenced_table_name, +], in relations.items(): + pass + +for ( + # leading comment + column_name, [ + referenced_column_name, + referenced_table_name, +]) in relations.items(): + pass + diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/function.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/function.py index 2c9450a926cfc..e5a32ad8884b7 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/function.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/function.py @@ -66,6 +66,52 @@ def argument_with_long_type_annotation( def test(): ... +# Type parameter empty line spacing +def test[ + # comment + A, + + # another + + B, +](): ... + + +# Type parameter comments +def type_param_comments[ # trailing bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +](): + # body comment + pass + + +# Note empty type parameters is not valid syntax, e.g. +# def test[](): ... + + +# Different type parameter wrappings + +def single_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccccccccc](): + pass + +def params_on_their_own_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccc, Ddddddddddddd, Eeeeeeee](): + pass + +def param_per_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccccccccc, Ddddddddddddd, Eeeeeeeeeeeeeeeee, ffffffffffff](): + pass + +def single_line_trailing_comma[A, B, C,](): + pass + # Comment def with_leading_comment(): ... @@ -231,3 +277,102 @@ def f42( c, ): pass + + +# Check trailing commas are permitted in funcdef argument list. +def f(a, ): pass +def f(*args, ): pass +def f(**kwds, ): pass +def f(a, *args, ): pass +def f(a, **kwds, ): pass +def f(*args, b, ): pass +def f(*, b, ): pass +def f(*args, **kwds, ): pass +def f(a, *args, b, ): pass +def f(a, *, b, ): pass +def f(a, *args, **kwds, ): pass +def f(*args, b, **kwds, ): pass +def f(*, b, **kwds, ): pass +def f(a, *args, b, **kwds, ): pass +def f(a, *, b, **kwds, ): pass + +# Handle comments on open parenthesis. +def f( + # first + # second +): + ... + + +def f( # first + # second +): # third + ... + + +def f( # first +): # second + ... + + +def f( + a, + /, + # first + b + # second +): + ... + + +def f( # first + *, + # second + b + # third +): + ... + + +def f( # first + # second + *, + # third + b + # fourth +): + ... + + +def f( # first + a, + # second +): # third + ... + + +def f( # first + a +): # second + ... + + +def f( # first + a + # second +): # third + ... + + +def f( # first + a, + / # second + , + # third +): + ... + +# Walrus operator in return type. +def this_is_unusual() -> (please := no): ... + +def this_is_unusual(x) -> (please := no): ... diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/global.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/global.py index faec9b9e81ff7..1048e9922353e 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/global.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/global.py @@ -10,3 +10,7 @@ def f(): def f(): global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + + +def f(): + global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if.py index 266b2da8a733d..61e3bc130b864 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if.py @@ -103,3 +103,15 @@ def f(): if True: print("a") # 1 elif True: print("b") # 2 else: print("c") # 3 + +# Regression test for https://github.com/astral-sh/ruff/issues/5337 +if parent_body: + if current_body: + child_in_body() + last_child_in_current_body() # may or may not have children on its own +# a + # b + # c + # d + # e + #f diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py index 1677400431dd0..db6590784767f 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py @@ -1,3 +1,58 @@ from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd + +# At the top-level, force one empty line after an import, but allow up to two empty +# lines. +import os +import sys +x = 1 + +import os +import sys + +x = 1 + +import os +import sys + + +x = 1 + +import os +import sys + + + +x = 1 + + +# In a nested scope, force one empty line after an import. +def func(): + import os + import sys + x = 1 + + +def func(): + import os + import sys + + x = 1 + + +def func(): + import os + import sys + + + x = 1 + + +def func(): + import os + import sys + + + + x = 1 diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py index 335e91036abf9..43376564abd0b 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py @@ -14,3 +14,24 @@ aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, ) from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * + + +from a import bar # comment + +from a import bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar # comment + +from a import ( # comment + bar, +) + +from a import ( # comment + bar +) + +from a import bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar +# comment + +from a import \ + ( # comment + bar, +) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py new file mode 100644 index 0000000000000..421055cec944e --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py @@ -0,0 +1,401 @@ +# leading match comment +match foo: # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # leading expr comment + # another leading expr comment + foo # trailing expr comment + # another trailing expr comment +): # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # hello + foo # trailing expr comment + , # another +): # dangling match comment + case "bar": + pass + + +match [ # comment + first, + second, + third +]: # another comment + case ["a", "b", "c"]: + pass + +match ( # comment + "a b c" +).split(): # another comment + case ["a", "b", "c"]: + pass + + +match ( # comment + # let's go + yield foo +): # another comment + case ["a", "b", "c"]: + pass + + +match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment + case "sshhhhhhhh": + pass + + +def foo(): + match inside_func: # comment + case "bar": + pass + + +match newlines: + + # case 1 leading comment + + + case "top level case comment with newlines": # case dangling comment + # pass leading comment + pass + # pass trailing comment + + + # case 2 leading comment + + + + case "case comment with newlines" if foo == 2: # second + pass + + case "one", "newline" if (foo := 1): # third + pass + + + case "two newlines": + pass + + + + case "three newlines": + pass + case _: + pass + + +match long_lines: + case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment + pass + + case "this is a long line for if condition with parentheses" if (aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2): # comment + pass + + case "named expressions aren't special" if foo := 1: + pass + + case "named expressions aren't that special" if (foo := 1): + pass + + case "but with already broken long lines" if ( + aaaaaaahhhhhhhhhhh == 1 and + bbbbbbbbaaaaaahhhh == 2 + ): # another comment + pass + + +match pattern_comments: + case ( + only_trailing # trailing 1 + # trailing 2 +# trailing 3 + ): + pass + + +match pattern_comments: + case ( # leading + only_leading + ): + pass + + +match pattern_comments: + case ( + # leading + leading_and_trailing # trailing 1 + # trailing 2 +# trailing 3 + ): + pass + + +match pattern_comments: + case ( + no_comments + ): + pass + + +match pattern_comments: + case ( + # 1 + pattern # 2 + # 3 + as # 4 + # 5 + name # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as # 2 + # 3 + name #4 + # 5 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as + # 2 + name + # 3 + ): + pass + + +match subject: + case ( + pattern # 1 + as # 2 + name # 3 + ): + pass + + +match x: + case (a as b) as c: + pass + + +match pattern_singleton: + case ( + # leading 1 + # leading 2 + None # trailing + # trailing own 1 + # trailing own 2 + ): + pass + case ( + True # trailing + ): + ... + case False: + ... + + +match foo: + case "a", "b": + pass + case "a", "b",: + pass + case ("a", "b"): + pass + case ["a", "b"]: + pass + case (["a", "b"]): + pass + + +match foo: + case [ # leading +# leading + # leading + # leading + "a", # trailing +# trailing + # trailing + # trailing + "b", + ]: + pass + +match foo: + case 1: + y = 0 + case (1): + y = 1 + case (("a")): + y = 1 + case ( # comment + 1 + ): + y = 1 + case ( + # comment + 1 + ): + y = 1 + case ( + 1 # comment + ): + y = 1 + case ( + 1 + # comment + ): + y = 1 + + +match foo: + case [1, 2, *rest]: + pass + case [1, 2, *_]: + pass + case [*rest, 1, 2]: + pass + case [*_, 1, 2]: + pass + case [ + 1, + 2, + *rest, + ]: + pass + case [1, 2, * # comment + rest]: + pass + case [1, 2, * # comment + _]: + pass + case [* # comment + rest, 1, 2]: + pass + case [* # comment + _, 1, 2]: + pass + case [* # end of line + # own line + _, 1, 2]: + pass + case [* # end of line + # own line + _, 1, 2]: + pass + + +match foo: + case (1): + pass + case ((1)): + pass + case [(1), 2]: + pass + case [( # comment + 1 + ), 2]: + pass + case [ # outer + ( # inner + 1 + ), 2]: + pass + case [ + ( # outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + ( # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + # own line + ( # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [(*rest), (a as b)]: + pass + + +match foo: + case {"a": 1, "b": 2}: + pass + + case { + # own line + "a": 1, # end-of-line + # own line + "b": 2, + }: + pass + + case { # open + 1 # key + : # colon + value # value + }: + pass + + case {**d}: + pass + + case { + ** # middle with single item + b + }: + pass + + case { + # before + ** # between + b, + }: + pass + + case { + 1: x, + # foo + ** # bop + # before + b, # boo + # baz + }: + pass + + case { + 1: x + # foo + , + ** + b, + }: + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/nonlocal.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/nonlocal.py index 2699c513bf9a0..98df4df83252a 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/nonlocal.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/nonlocal.py @@ -10,3 +10,7 @@ def f(): def f(): nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + + +def f(): + nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/return_annotation.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/return_annotation.py new file mode 100644 index 0000000000000..f7b043d477399 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/return_annotation.py @@ -0,0 +1,182 @@ +# Handle comments on empty tuple return types. +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + # comment +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + 1 +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + 1, 2 +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + (1, 2) +): ... + +def handleMatch( # type: ignore[override] # https://github.com/python/mypy/issues/10197 + self, m: Match[str], data: str +) -> Union[Tuple[None, None, None], Tuple[Element, int, int]]: + ... + +def double(a: int # Hello +) -> (int): + return 2 * a + +def double(a: int) -> ( # Hello + int +): + return 2*a + +def double(a: int) -> ( # Hello +): + return 2*a + +# Breaking over parameters and return types. (Black adds a trailing comma when the +# function arguments break here with a single argument; we do not.) +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a: + ... + +def f(a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> a: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a: + ... + +# Breaking return type annotations. Black adds parentheses if the parameters are +# empty; otherwise, it leverages the expressions own parentheses if possible. +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(*args) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( # foo +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + # bar +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X + Y + foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X + Y + foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X and Y and foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X and Y and foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X | Y | foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X | Y | foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + + +def double() -> first_item and foo.bar.baz().bop(1,): + return 2 * a + + +# Dangling comments on return annotations. +def double(a: int) -> ( + int # Hello +): + return 2*a + +def double(a: int) -> ( + foo.bar # Hello +): + return 2*a + +def double(a: int) -> ( + [int] # Hello +): + return 2*a + +def double(a: int) -> ( + int | list[int] # Hello +): + pass + +def double(a: int) -> ( + int | list[int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int] # Hello +): + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.py new file mode 100644 index 0000000000000..85210a209eca1 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.py @@ -0,0 +1,39 @@ +class A: + def __init__(self): + pass + +class B: + def __init__(self): + pass + +def foo(): + pass + +class Del(expr_context): ... +class Load(expr_context): ... + +# Some comment. +class Other(expr_context): ... +class Store(expr_context): ... +class Foo(Bar): ... + +class Baz(Qux): + def __init__(self): + pass + +class Quux(Qux): + def __init__(self): + pass + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + +def bar(): ... +def baz(): ... +def quux(): + """Some docstring.""" + +def quuz(): + """Some docstring.""" diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.pyi b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.pyi new file mode 100644 index 0000000000000..2f359bf10801f --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.pyi @@ -0,0 +1,91 @@ +class A: + def __init__(self): + pass + + +class B: + def __init__(self): + pass + + +def foo(): + pass + + +class Del(expr_context): + ... + + +class Load(expr_context): + ... + + +# Some comment. +class Other(expr_context): + ... + + +class Store(expr_context): + ... + + +class Foo(Bar): + ... + + +class Baz(Qux): + def __init__(self): + pass + + +class Quux(Qux): + def __init__(self): + pass + + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + + +def bar(): + ... + + +def baz(): + ... + + +def quux(): + """Some docstring.""" + + +def quuz(): + """Some docstring.""" + +def a(): + ... + +class Test: + ... + +class Test2(A): + ... + +def b(): ... +# comment +def c(): ... + +class EllipsisWithComment: + ... # comment + +def function_with_comment(): + ... # comment + +class EllispsisWithMultipleTrailing: # trailing class comment + ... # trailing ellipsis comment + +class EllipsisWithLeadingComment: + # leading + ... diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py index 1209c97470e49..bb61b909a248c 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/try.py @@ -138,3 +138,31 @@ def f(): print(3) # 8 preceding: last in body, following: fist in alt body, enclosing: try finally: # 9 preceding: last in body, following: fist in alt body, enclosing: try print(3) # 10 preceding: last in body, following: any, enclosing: try + +try: + pass +except ( + ZeroDivisionError + # comment +): + pass + + +try: + pass + +finally: + pass + + +try: + pass + +except ZeroDivisonError: + pass + +else: + pass + +finally: + pass diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py index 69f3cdafd5068..c50a35a0440e3 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py @@ -1,4 +1,4 @@ -# Copied from https://github.com/RustPython/Parser/blob/704eb40108239a8faf9bd1d4217e8dad0ac7edb3/parser/src/parser.rs#L901-L936 +# basic usage type X = int type X = int | str @@ -10,6 +10,17 @@ type X[T: int, *Ts, **P] = (T, Ts, P) type X[T: (int, str), *Ts, **P] = (T, Ts, P) +# long name +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[A] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt + +# long value +type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type X = Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + # soft keyword as alias name type type = int type match = int @@ -36,3 +47,44 @@ [T] = T type X[T] \ = T + +# type leading comment +type X = ( # trailing open paren comment + # value leading comment + int # value trailing comment + # leading close paren comment +) # type trailing comment + + +# type leading comment +type X = ( + # value leading comment + int # value trailing comment + + # leading close paren comment +) + +# type parameters +type type_params_single_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc] = int +type type_params_arguments_on_their_own_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccc, ddddddddddddd, eeeeeee] = int +type type_params_argument_per_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc, ddddddddddddd, eeeeeeeeeeeeeeee, ffffffffffff] = int +type type_params_trailing_comma[a, b,] = int +type type_params_comments[ # trailing open bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading close bracket comment +] = int # trailing value comment +type type_params_all_kinds[type_var, *type_var_tuple, **param_spec] = int + +# type variable bounds +type bounds_single_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc)] = T +type bounds_arguments_on_their_own_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccc, ddddddddddddd, eeeeeee)] = T +type bounds_argument_per_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc, ddddddddddddd, eeeeeeeeeeeeeeee, ffffffffffff)] = T +type bounds_trailing_comma[T: (a, b,)] = T diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py index 76a8a49950737..03ab7a0a3b8ff 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py @@ -67,6 +67,24 @@ a as b ): ... +with ( + a as b + # trailing comment +): ... + +with ( + a as ( + # leading comment + b + ) +): ... + +with ( + a as ( + b + # trailing comment + ) +): ... with (a # trailing same line comment # trailing own line comment @@ -78,7 +96,6 @@ as b ): ... - with (a # trailing same line comment # trailing own line comment ) as b: ... @@ -108,7 +125,6 @@ ): ... - with [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", @@ -116,3 +132,125 @@ dddddddddddddddddddddddddddddddd, ] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2: ... + +# Comments on open parentheses +with ( # comment + CtxManager1() as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ) as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + CtxManager() +) as example: + ... + +with ( # outer comment + CtxManager() +) as example, ( # inner comment + CtxManager2() +) as example2: + ... + +with ( # outer comment + CtxManager1(), + CtxManager2(), +) as example: + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ), + CtxManager2(), +) as example: + ... + +# Breaking of with items. +with (test # bar + as # foo + ( + # test + foo)): + pass + +with test as ( + # test + foo): + pass + +with (test # bar + as # foo + ( # baz + # test + foo)): + pass + +with (a as b, c as d): + pass + +with ( + a as b, + # foo + c as d +): + pass + +with ( + a as ( # foo + b + ) +): + pass + +with ( + f(a, ) as b + +): + pass + +with (x := 1) as d: + pass + +with (x[1, 2,] as d): + pass + +with (f(a, ) as b, c as d): + pass + +with f(a, ) as b, c as d: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) as b: + pass + +with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) as b, c as d: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, c as d): + pass + +with ( + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) as b, c as d): + pass + +with (foo() as bar, baz() as bop): + pass diff --git a/crates/ruff_python_formatter/src/builders.rs b/crates/ruff_python_formatter/src/builders.rs index 9a0ebe93f06bb..56f2936b7c975 100644 --- a/crates/ruff_python_formatter/src/builders.rs +++ b/crates/ruff_python_formatter/src/builders.rs @@ -1,12 +1,10 @@ use ruff_formatter::{format_args, write, Argument, Arguments}; use ruff_python_ast::Ranged; -use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{TextRange, TextSize}; -use crate::comments::{dangling_comments, SourceComment}; use crate::context::{NodeLevel, WithNodeLevel}; +use crate::other::commas::has_magic_trailing_comma; use crate::prelude::*; -use crate::MagicTrailingComma; /// Adds parentheses and indents `content` if it doesn't fit on a line. pub(crate) fn parenthesize_if_expands<'ast, T>(content: &T) -> ParenthesizeIfExpands<'_, 'ast> @@ -93,11 +91,23 @@ impl Entries { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub(crate) enum TrailingComma { + /// Add a trailing comma if the group breaks and there's more than one element (or if the last + /// element has a trailing comma and the magical trailing comma option is enabled). + #[default] + MoreThanOne, + /// Add a trailing comma if the group breaks (or if the last element has a trailing comma and + /// the magical trailing comma option is enabled). + OneOrMore, +} + pub(crate) struct JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { result: FormatResult<()>, fmt: &'fmt mut PyFormatter<'ast, 'buf>, entries: Entries, sequence_end: TextSize, + trailing_comma: TrailingComma, } impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { @@ -107,9 +117,19 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { result: Ok(()), entries: Entries::None, sequence_end, + trailing_comma: TrailingComma::default(), } } + /// Set the trailing comma behavior for the builder. Trailing commas will only be inserted if + /// the group breaks, and will _always_ be inserted if the last element has a trailing comma + /// (and the magical trailing comma option is enabled). However, this setting dictates whether + /// trailing commas are inserted for single element groups. + pub(crate) fn with_trailing_comma(mut self, trailing_comma: TrailingComma) -> Self { + self.trailing_comma = trailing_comma; + self + } + pub(crate) fn entry( &mut self, node: &T, @@ -173,30 +193,18 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { pub(crate) fn finish(&mut self) -> FormatResult<()> { self.result.and_then(|_| { if let Some(last_end) = self.entries.position() { - let magic_trailing_comma = match self.fmt.options().magic_trailing_comma() { - MagicTrailingComma::Respect => { - let first_token = SimpleTokenizer::new( - self.fmt.context().source(), - TextRange::new(last_end, self.sequence_end), - ) - .skip_trivia() - // Skip over any closing parentheses belonging to the expression - .find(|token| token.kind() != SimpleTokenKind::RParen); - - matches!( - first_token, - Some(SimpleToken { - kind: SimpleTokenKind::Comma, - .. - }) - ) - } - MagicTrailingComma::Ignore => false, - }; + let magic_trailing_comma = has_magic_trailing_comma( + TextRange::new(last_end, self.sequence_end), + self.fmt.options(), + self.fmt.context(), + ); // If there is a single entry, only keep the magic trailing comma, don't add it if - // it wasn't there. If there is more than one entry, always add it. - if magic_trailing_comma || self.entries.is_more_than_one() { + // it wasn't there -- unless the trailing comma behavior is set to one-or-more. + if magic_trailing_comma + || self.trailing_comma == TrailingComma::OneOrMore + || self.entries.is_more_than_one() + { if_group_breaks(&text(",")).fmt(self.fmt)?; } @@ -209,54 +217,3 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { }) } } - -/// Format comments inside empty parentheses, brackets or curly braces. -/// -/// Empty `()`, `[]` and `{}` are special because there can be dangling comments, and they can be in -/// two positions: -/// ```python -/// x = [ # end-of-line -/// # own line -/// ] -/// ``` -/// These comments are dangling because they can't be assigned to any element inside as they would -/// in all other cases. -pub(crate) fn empty_parenthesized_with_dangling_comments( - opening: StaticText, - comments: &[SourceComment], - closing: StaticText, -) -> EmptyWithDanglingComments { - EmptyWithDanglingComments { - opening, - comments, - closing, - } -} - -pub(crate) struct EmptyWithDanglingComments<'a> { - opening: StaticText, - comments: &'a [SourceComment], - closing: StaticText, -} - -impl<'ast> Format> for EmptyWithDanglingComments<'_> { - fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { - let end_of_line_split = self - .comments - .partition_point(|comment| comment.line_position().is_end_of_line()); - debug_assert!(self.comments[end_of_line_split..] - .iter() - .all(|comment| comment.line_position().is_own_line())); - write!( - f, - [group(&format_args![ - self.opening, - // end-of-line comments - dangling_comments(&self.comments[..end_of_line_split]), - // own line comments, which need to be indented - soft_block_indent(&dangling_comments(&self.comments[end_of_line_split..])), - self.closing - ])] - ) - } -} diff --git a/crates/ruff_python_formatter/src/cli.rs b/crates/ruff_python_formatter/src/cli.rs index 132798486a581..fff146fdb91cd 100644 --- a/crates/ruff_python_formatter/src/cli.rs +++ b/crates/ruff_python_formatter/src/cli.rs @@ -1,14 +1,14 @@ #![allow(clippy::print_stdout)] -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use anyhow::{bail, Context, Result}; use clap::{command, Parser, ValueEnum}; -use ruff_python_parser::lexer::lex; -use ruff_python_parser::{parse_tokens, Mode}; use ruff_formatter::SourceCode; use ruff_python_index::CommentRangesBuilder; +use ruff_python_parser::lexer::lex; +use ruff_python_parser::{parse_tokens, Mode}; use crate::{format_node, PyFormatOptions}; @@ -37,7 +37,7 @@ pub struct Cli { pub print_comments: bool, } -pub fn format_and_debug_print(input: &str, cli: &Cli) -> Result { +pub fn format_and_debug_print(input: &str, cli: &Cli, source_type: &Path) -> Result { let mut tokens = Vec::new(); let mut comment_ranges = CommentRangesBuilder::default(); @@ -57,13 +57,9 @@ pub fn format_and_debug_print(input: &str, cli: &Cli) -> Result { let python_ast = parse_tokens(tokens, Mode::Module, "").context("Syntax error in input")?; - let formatted = format_node( - &python_ast, - &comment_ranges, - input, - PyFormatOptions::default(), - ) - .context("Failed to format node")?; + let options = PyFormatOptions::from_extension(source_type); + let formatted = format_node(&python_ast, &comment_ranges, input, options) + .context("Failed to format node")?; if cli.print_ir { println!("{}", formatted.document().display(SourceCode::new(input))); } diff --git a/crates/ruff_python_formatter/src/comments/format.rs b/crates/ruff_python_formatter/src/comments/format.rs index b5d7056fd09f5..7a36a3a406c2a 100644 --- a/crates/ruff_python_formatter/src/comments/format.rs +++ b/crates/ruff_python_formatter/src/comments/format.rs @@ -3,9 +3,9 @@ use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_formatter::{format_args, write, FormatError, SourceCode}; use ruff_python_ast::node::{AnyNodeRef, AstNode}; -use ruff_python_trivia::{lines_after, lines_before, skip_trailing_trivia}; +use ruff_python_trivia::{lines_after, lines_after_ignoring_trivia, lines_before}; -use crate::comments::SourceComment; +use crate::comments::{CommentLinePosition, SourceComment}; use crate::context::NodeLevel; use crate::prelude::*; @@ -33,7 +33,7 @@ impl Format> for FormatLeadingComments<'_> { let comments = f.context().comments().clone(); let leading_comments = match self { - FormatLeadingComments::Node(node) => comments.leading_comments(*node), + FormatLeadingComments::Node(node) => comments.leading(*node), FormatLeadingComments::Comments(comments) => comments, }; @@ -80,7 +80,7 @@ pub(crate) struct FormatLeadingAlternateBranchComments<'a> { } impl Format> for FormatLeadingAlternateBranchComments<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { if let Some(first_leading) = self.comments.first() { // Leading comments only preserves the lines after the comment but not before. // Insert the necessary lines. @@ -90,10 +90,9 @@ impl Format> for FormatLeadingAlternateBranchComments<'_> { write!(f, [leading_comments(self.comments)])?; } else if let Some(last_preceding) = self.last_node { - let full_end = skip_trailing_trivia(last_preceding.end(), f.context().source()); // The leading comments formatting ensures that it preserves the right amount of lines after // We need to take care of this ourselves, if there's no leading `else` comment. - if lines_after(full_end, f.context().source()) > 1 { + if lines_after_ignoring_trivia(last_preceding.end(), f.context().source()) > 1 { write!(f, [empty_line()])?; } } @@ -121,11 +120,11 @@ pub(crate) enum FormatTrailingComments<'a> { } impl Format> for FormatTrailingComments<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let comments = f.context().comments().clone(); let trailing_comments = match self { - FormatTrailingComments::Node(node) => comments.trailing_comments(*node), + FormatTrailingComments::Node(node) => comments.trailing(*node), FormatTrailingComments::Comments(comments) => comments, }; @@ -152,12 +151,10 @@ impl Format> for FormatTrailingComments<'_> { write!( f, [ - line_suffix(&format_with(|f| { - write!( - f, - [empty_lines(lines_before_comment), format_comment(trailing)] - ) - })), + line_suffix(&format_args![ + empty_lines(lines_before_comment), + format_comment(trailing) + ]), expand_parent() ] )?; @@ -201,7 +198,7 @@ impl Format> for FormatDanglingComments<'_> { let dangling_comments = match self { Self::Comments(comments) => comments, - Self::Node(node) => comments.dangling_comments(*node), + Self::Node(node) => comments.dangling(*node), }; let mut first = true; @@ -209,8 +206,15 @@ impl Format> for FormatDanglingComments<'_> { .iter() .filter(|comment| comment.is_unformatted()) { - if first && comment.line_position().is_end_of_line() { - write!(f, [space(), space()])?; + if first { + match comment.line_position { + CommentLinePosition::OwnLine => { + write!(f, [hard_line_break()])?; + } + CommentLinePosition::EndOfLine => { + write!(f, [space(), space()])?; + } + } } write!( @@ -230,20 +234,64 @@ impl Format> for FormatDanglingComments<'_> { } } +/// Formats the dangling comments within a parenthesized expression, for example: +/// ```python +/// [ # comment +/// 1, +/// 2, +/// 3, +/// ] +/// ``` +pub(crate) fn dangling_open_parenthesis_comments( + comments: &[SourceComment], +) -> FormatDanglingOpenParenthesisComments { + FormatDanglingOpenParenthesisComments { comments } +} + +pub(crate) struct FormatDanglingOpenParenthesisComments<'a> { + comments: &'a [SourceComment], +} + +impl Format> for FormatDanglingOpenParenthesisComments<'_> { + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + for comment in self + .comments + .iter() + .filter(|comment| comment.is_unformatted()) + { + debug_assert!( + comment.line_position().is_end_of_line(), + "Expected dangling comment to be at the end of the line" + ); + + write!( + f, + [ + line_suffix(&format_args!(space(), space(), format_comment(comment))), + expand_parent() + ] + )?; + comment.mark_formatted(); + } + + Ok(()) + } +} + /// Formats the content of the passed comment. /// /// * Adds a whitespace between `#` and the comment text except if the first character is a `#`, `:`, `'`, or `!` /// * Replaces non breaking whitespaces with regular whitespaces except if in front of a `types:` comment -const fn format_comment(comment: &SourceComment) -> FormatComment { +pub(crate) const fn format_comment(comment: &SourceComment) -> FormatComment { FormatComment { comment } } -struct FormatComment<'a> { +pub(crate) struct FormatComment<'a> { comment: &'a SourceComment, } impl Format> for FormatComment<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let slice = self.comment.slice(); let comment_text = slice.text(SourceCode::new(f.context().source())); @@ -280,7 +328,7 @@ impl Format> for FormatComment<'_> { } let start = slice.start() + start_offset; - let end = slice.range().end() - trailing_whitespace_len; + let end = slice.end() - trailing_whitespace_len; write!( f, @@ -296,12 +344,12 @@ impl Format> for FormatComment<'_> { // Top level: Up to two empty lines // parenthesized: A single empty line // other: Up to a single empty line -const fn empty_lines(lines: u32) -> FormatEmptyLines { +pub(crate) const fn empty_lines(lines: u32) -> FormatEmptyLines { FormatEmptyLines { lines } } #[derive(Copy, Clone, Debug)] -struct FormatEmptyLines { +pub(crate) struct FormatEmptyLines { lines: u32, } diff --git a/crates/ruff_python_formatter/src/comments/map.rs b/crates/ruff_python_formatter/src/comments/map.rs index 9bef831903d0c..7ef01dc736c7f 100644 --- a/crates/ruff_python_formatter/src/comments/map.rs +++ b/crates/ruff_python_formatter/src/comments/map.rs @@ -244,15 +244,29 @@ impl MultiMap { } /// Returns `true` if `key` has any *leading*, *dangling*, or *trailing* parts. + #[allow(unused)] pub(super) fn has(&self, key: &K) -> bool { self.index.get(key).is_some() } - /// Returns an iterator over the *leading*, *dangling*, and *trailing* parts of `key`. - pub(super) fn parts(&self, key: &K) -> PartsIterator { + /// Returns the *leading*, *dangling*, and *trailing* parts of `key`. + pub(super) fn leading_dangling_trailing(&self, key: &K) -> LeadingDanglingTrailing { match self.index.get(key) { - None => PartsIterator::Slice([].iter()), - Some(entry) => PartsIterator::from_entry(entry, self), + None => LeadingDanglingTrailing { + leading: &[], + dangling: &[], + trailing: &[], + }, + Some(Entry::InOrder(entry)) => LeadingDanglingTrailing { + leading: &self.parts[entry.leading_range()], + dangling: &self.parts[entry.dangling_range()], + trailing: &self.parts[entry.trailing_range()], + }, + Some(Entry::OutOfOrder(entry)) => LeadingDanglingTrailing { + leading: &self.out_of_order_parts[entry.leading_index()], + dangling: &self.out_of_order_parts[entry.dangling_index()], + trailing: &self.out_of_order_parts[entry.trailing_index()], + }, } } @@ -261,7 +275,7 @@ impl MultiMap { pub(super) fn all_parts(&self) -> impl Iterator { self.index .values() - .flat_map(|entry| PartsIterator::from_entry(entry, self)) + .flat_map(|entry| LeadingDanglingTrailing::from_entry(entry, self)) } } @@ -280,41 +294,30 @@ where let mut builder = f.debug_map(); for (key, entry) in &self.index { - builder.entry(&key, &DebugEntry { entry, map: self }); + builder.entry(&key, &LeadingDanglingTrailing::from_entry(entry, self)); } builder.finish() } } -/// Iterates over all *leading*, *dangling*, and *trailing* parts of a key. -pub(super) enum PartsIterator<'a, V> { - /// The slice into the [CommentsMap::parts] [Vec] if this is an in-order entry or the *trailing* parts - /// of an out-of-order entry. - Slice(std::slice::Iter<'a, V>), - - /// Iterator over the *leading* parts of an out-of-order entry. Returns the *dangling* parts, and then the - /// *trailing* parts once the *leading* iterator is fully consumed. - Leading { - leading: std::slice::Iter<'a, V>, - dangling: &'a [V], - trailing: &'a [V], - }, - - /// Iterator over the *dangling* parts of an out-of-order entry. Returns the *trailing* parts - /// once the *leading* iterator is fully consumed. - Dangling { - dangling: std::slice::Iter<'a, V>, - trailing: &'a [V], - }, +#[derive(Clone)] +pub(crate) struct LeadingDanglingTrailing<'a, T> { + pub(crate) leading: &'a [T], + pub(crate) dangling: &'a [T], + pub(crate) trailing: &'a [T], } -impl<'a, V> PartsIterator<'a, V> { - fn from_entry(entry: &Entry, map: &'a MultiMap) -> Self { +impl<'a, T> LeadingDanglingTrailing<'a, T> { + fn from_entry(entry: &Entry, map: &'a MultiMap) -> Self { match entry { - Entry::InOrder(entry) => PartsIterator::Slice(map.parts[entry.range()].iter()), - Entry::OutOfOrder(entry) => PartsIterator::Leading { - leading: map.out_of_order_parts[entry.leading_index()].iter(), + Entry::InOrder(entry) => LeadingDanglingTrailing { + leading: &map.parts[entry.leading_range()], + dangling: &map.parts[entry.dangling_range()], + trailing: &map.parts[entry.trailing_range()], + }, + Entry::OutOfOrder(entry) => LeadingDanglingTrailing { + leading: &map.out_of_order_parts[entry.leading_index()], dangling: &map.out_of_order_parts[entry.dangling_index()], trailing: &map.out_of_order_parts[entry.trailing_index()], }, @@ -322,252 +325,42 @@ impl<'a, V> PartsIterator<'a, V> { } } -impl<'a, V> Iterator for PartsIterator<'a, V> { - type Item = &'a V; - - fn next(&mut self) -> Option { - match self { - PartsIterator::Slice(inner) => inner.next(), - - PartsIterator::Leading { - leading, - dangling, - trailing, - } => match leading.next() { - Some(next) => Some(next), - None if !dangling.is_empty() => { - let mut dangling_iterator = dangling.iter(); - let next = dangling_iterator.next().unwrap(); - *self = PartsIterator::Dangling { - dangling: dangling_iterator, - trailing, - }; - Some(next) - } - None => { - let mut trailing_iterator = trailing.iter(); - let next = trailing_iterator.next(); - *self = PartsIterator::Slice(trailing_iterator); - next - } - }, - - PartsIterator::Dangling { dangling, trailing } => dangling.next().or_else(|| { - let mut trailing_iterator = trailing.iter(); - let next = trailing_iterator.next(); - *self = PartsIterator::Slice(trailing_iterator); - next - }), - } - } - - fn fold(self, init: B, f: F) -> B - where - F: FnMut(B, Self::Item) -> B, - { - match self { - PartsIterator::Slice(slice) => slice.fold(init, f), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading - .chain(dangling.iter()) - .chain(trailing.iter()) - .fold(init, f), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).fold(init, f) - } - } - } - - fn all(&mut self, f: F) -> bool - where - F: FnMut(Self::Item) -> bool, - { - match self { - PartsIterator::Slice(slice) => slice.all(f), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading.chain(dangling.iter()).chain(trailing.iter()).all(f), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).all(f) - } - } - } - - fn any(&mut self, f: F) -> bool - where - F: FnMut(Self::Item) -> bool, - { - match self { - PartsIterator::Slice(slice) => slice.any(f), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading.chain(dangling.iter()).chain(trailing.iter()).any(f), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).any(f) - } - } - } +impl<'a, T> IntoIterator for LeadingDanglingTrailing<'a, T> { + type Item = &'a T; + type IntoIter = std::iter::Chain< + std::iter::Chain, std::slice::Iter<'a, T>>, + std::slice::Iter<'a, T>, + >; - fn find

(&mut self, predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - match self { - PartsIterator::Slice(slice) => slice.find(predicate), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading - .chain(dangling.iter()) - .chain(trailing.iter()) - .find(predicate), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).find(predicate) - } - } - } - - fn find_map(&mut self, f: F) -> Option - where - F: FnMut(Self::Item) -> Option, - { - match self { - PartsIterator::Slice(slice) => slice.find_map(f), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading - .chain(dangling.iter()) - .chain(trailing.iter()) - .find_map(f), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).find_map(f) - } - } - } - - fn position

(&mut self, predicate: P) -> Option - where - P: FnMut(Self::Item) -> bool, - { - match self { - PartsIterator::Slice(slice) => slice.position(predicate), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => leading - .chain(dangling.iter()) - .chain(trailing.iter()) - .position(predicate), - PartsIterator::Dangling { dangling, trailing } => { - dangling.chain(trailing.iter()).position(predicate) - } - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - PartsIterator::Slice(slice) => slice.size_hint(), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => { - let len = leading.len() + dangling.len() + trailing.len(); - - (len, Some(len)) - } - PartsIterator::Dangling { dangling, trailing } => { - let len = dangling.len() + trailing.len(); - (len, Some(len)) - } - } - } - - fn count(self) -> usize { - self.size_hint().0 - } - - fn last(self) -> Option { - match self { - PartsIterator::Slice(slice) => slice.last(), - PartsIterator::Leading { - leading, - dangling, - trailing, - } => trailing - .last() - .or_else(|| dangling.last()) - .or_else(|| leading.last()), - PartsIterator::Dangling { dangling, trailing } => { - trailing.last().or_else(|| dangling.last()) - } - } + fn into_iter(self) -> Self::IntoIter { + self.leading + .iter() + .chain(self.dangling) + .chain(self.trailing) } } -impl ExactSizeIterator for PartsIterator<'_, V> {} - -impl FusedIterator for PartsIterator<'_, V> {} - -#[derive(Clone, Debug)] -enum Entry { - InOrder(InOrderEntry), - OutOfOrder(OutOfOrderEntry), -} - -struct DebugEntry<'a, K, V> { - entry: &'a Entry, - map: &'a MultiMap, -} - -impl Debug for DebugEntry<'_, K, V> +impl<'a, T> Debug for LeadingDanglingTrailing<'a, T> where - K: Debug, - V: Debug, + T: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let leading = match self.entry { - Entry::OutOfOrder(entry) => { - self.map.out_of_order_parts[entry.leading_index()].as_slice() - } - Entry::InOrder(entry) => &self.map.parts[entry.leading_range()], - }; - - let dangling = match self.entry { - Entry::OutOfOrder(entry) => { - self.map.out_of_order_parts[entry.dangling_index()].as_slice() - } - Entry::InOrder(entry) => &self.map.parts[entry.dangling_range()], - }; - - let trailing = match self.entry { - Entry::OutOfOrder(entry) => { - self.map.out_of_order_parts[entry.trailing_index()].as_slice() - } - Entry::InOrder(entry) => &self.map.parts[entry.trailing_range()], - }; - let mut list = f.debug_list(); - list.entries(leading.iter().map(DebugValue::Leading)); - list.entries(dangling.iter().map(DebugValue::Dangling)); - list.entries(trailing.iter().map(DebugValue::Trailing)); + list.entries(self.leading.iter().map(DebugValue::Leading)); + list.entries(self.dangling.iter().map(DebugValue::Dangling)); + list.entries(self.trailing.iter().map(DebugValue::Trailing)); list.finish() } } +#[derive(Clone, Debug)] +enum Entry { + InOrder(InOrderEntry), + OutOfOrder(OutOfOrderEntry), +} + enum DebugValue<'a, V> { Leading(&'a V), Dangling(&'a V), @@ -810,7 +603,10 @@ mod tests { assert!(map.has(&"a")); assert_eq!( - map.parts(&"a").copied().collect::>(), + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), vec![1, 2, 3, 4] ); } @@ -831,7 +627,13 @@ mod tests { assert!(map.has(&"a")); - assert_eq!(map.parts(&"a").copied().collect::>(), vec![1, 2, 3]); + assert_eq!( + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), + vec![1, 2, 3] + ); } #[test] @@ -849,7 +651,13 @@ mod tests { assert!(map.has(&"a")); - assert_eq!(map.parts(&"a").copied().collect::>(), vec![1, 2]); + assert_eq!( + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), + vec![1, 2] + ); } #[test] @@ -865,7 +673,10 @@ mod tests { assert!(!map.has(&"a")); assert_eq!( - map.parts(&"a").copied().collect::>(), + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), Vec::::new() ); } @@ -886,22 +697,46 @@ mod tests { assert_eq!(map.leading(&"a"), &[1]); assert_eq!(map.dangling(&"a"), &EMPTY); assert_eq!(map.trailing(&"a"), &EMPTY); - assert_eq!(map.parts(&"a").copied().collect::>(), vec![1]); + assert_eq!( + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), + vec![1] + ); assert_eq!(map.leading(&"b"), &EMPTY); assert_eq!(map.dangling(&"b"), &[2]); assert_eq!(map.trailing(&"b"), &EMPTY); - assert_eq!(map.parts(&"b").copied().collect::>(), vec![2]); + assert_eq!( + map.leading_dangling_trailing(&"b") + .into_iter() + .copied() + .collect::>(), + vec![2] + ); assert_eq!(map.leading(&"c"), &EMPTY); assert_eq!(map.dangling(&"c"), &EMPTY); assert_eq!(map.trailing(&"c"), &[3]); - assert_eq!(map.parts(&"c").copied().collect::>(), vec![3]); + assert_eq!( + map.leading_dangling_trailing(&"c") + .into_iter() + .copied() + .collect::>(), + vec![3] + ); assert_eq!(map.leading(&"d"), &[4]); assert_eq!(map.dangling(&"d"), &[5]); assert_eq!(map.trailing(&"d"), &[6]); - assert_eq!(map.parts(&"d").copied().collect::>(), vec![4, 5, 6]); + assert_eq!( + map.leading_dangling_trailing(&"d") + .into_iter() + .copied() + .collect::>(), + vec![4, 5, 6] + ); } #[test] @@ -918,7 +753,10 @@ mod tests { assert_eq!(map.trailing(&"a"), [4]); assert_eq!( - map.parts(&"a").copied().collect::>(), + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), vec![2, 1, 3, 4] ); @@ -939,7 +777,10 @@ mod tests { assert_eq!(map.trailing(&"a"), [1, 4]); assert_eq!( - map.parts(&"a").copied().collect::>(), + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), vec![2, 3, 1, 4] ); @@ -958,7 +799,13 @@ mod tests { assert_eq!(map.dangling(&"a"), &[2]); assert_eq!(map.trailing(&"a"), &[1, 3]); - assert_eq!(map.parts(&"a").copied().collect::>(), vec![2, 1, 3]); + assert_eq!( + map.leading_dangling_trailing(&"a") + .into_iter() + .copied() + .collect::>(), + vec![2, 1, 3] + ); assert!(map.has(&"a")); } diff --git a/crates/ruff_python_formatter/src/comments/mod.rs b/crates/ruff_python_formatter/src/comments/mod.rs index 9cfb280e3d747..d46014ae29711 100644 --- a/crates/ruff_python_formatter/src/comments/mod.rs +++ b/crates/ruff_python_formatter/src/comments/mod.rs @@ -95,20 +95,23 @@ use std::rc::Rc; use ruff_python_ast::{Mod, Ranged}; pub(crate) use format::{ - dangling_comments, dangling_node_comments, leading_alternate_branch_comments, leading_comments, - leading_node_comments, trailing_comments, trailing_node_comments, + dangling_comments, dangling_node_comments, dangling_open_parenthesis_comments, + leading_alternate_branch_comments, leading_comments, leading_node_comments, trailing_comments, + trailing_node_comments, }; use ruff_formatter::{SourceCode, SourceCodeSlice}; use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::visitor::preorder::{PreorderVisitor, TraversalSignal}; use ruff_python_index::CommentRanges; +use ruff_python_trivia::PythonWhitespace; use crate::comments::debug::{DebugComment, DebugComments}; -use crate::comments::map::MultiMap; +use crate::comments::map::{LeadingDanglingTrailing, MultiMap}; use crate::comments::node_key::NodeRefEqualityKey; use crate::comments::visitor::CommentsVisitor; mod debug; -mod format; +pub(crate) mod format; mod map; mod node_key; mod placement; @@ -148,6 +151,11 @@ impl SourceComment { self.formatted.set(true); } + /// Marks the comment as not-formatted + pub(crate) fn mark_unformatted(&self) { + self.formatted.set(false); + } + /// If the comment has already been formatted pub(crate) fn is_formatted(&self) -> bool { self.formatted.get() @@ -161,6 +169,62 @@ impl SourceComment { pub(crate) fn debug<'a>(&'a self, source_code: SourceCode<'a>) -> DebugComment<'a> { DebugComment::new(self, source_code) } + + pub(crate) fn suppression_kind(&self, source: &str) -> Option { + let text = self.slice.text(SourceCode::new(source)); + let trimmed = text.strip_prefix('#').unwrap_or(text).trim_whitespace(); + + if let Some(command) = trimmed.strip_prefix("fmt:") { + match command.trim_whitespace_start() { + "off" => Some(SuppressionKind::Off), + "on" => Some(SuppressionKind::On), + "skip" => Some(SuppressionKind::Skip), + _ => None, + } + } else if let Some(command) = trimmed.strip_prefix("yapf:") { + match command.trim_whitespace_start() { + "disable" => Some(SuppressionKind::Off), + "enable" => Some(SuppressionKind::On), + _ => None, + } + } else { + None + } + } + + /// Returns true if this comment is a `fmt: off` or `yapf: disable` own line suppression comment. + pub(crate) fn is_suppression_off_comment(&self, source: &str) -> bool { + self.line_position.is_own_line() + && matches!(self.suppression_kind(source), Some(SuppressionKind::Off)) + } + + /// Returns true if this comment is a `fmt: on` or `yapf: enable` own line suppression comment. + pub(crate) fn is_suppression_on_comment(&self, source: &str) -> bool { + self.line_position.is_own_line() + && matches!(self.suppression_kind(source), Some(SuppressionKind::On)) + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub(crate) enum SuppressionKind { + /// A `fmt: off` or `yapf: disable` comment + Off, + /// A `fmt: on` or `yapf: enable` comment + On, + /// A `fmt: skip` comment + Skip, +} + +impl SuppressionKind { + pub(crate) fn has_skip_comment(trailing_comments: &[SourceComment], source: &str) -> bool { + trailing_comments.iter().any(|comment| { + comment.line_position().is_end_of_line() + && matches!( + comment.suppression_kind(source), + Some(SuppressionKind::Skip | SuppressionKind::Off) + ) + }) + } } impl Ranged for SourceComment { @@ -244,8 +308,6 @@ pub(crate) struct Comments<'a> { data: Rc>, } -#[allow(unused)] -// TODO(micha): Remove after using the new comments infrastructure in the formatter. impl<'a> Comments<'a> { fn new(comments: CommentsMap<'a>) -> Self { Self { @@ -268,28 +330,18 @@ impl<'a> Comments<'a> { Self::new(map) } - #[inline] - pub(crate) fn has_comments(&self, node: T) -> bool - where - T: Into>, - { - self.data - .comments - .has(&NodeRefEqualityKey::from_ref(node.into())) - } - /// Returns `true` if the given `node` has any [leading comments](self#leading-comments). #[inline] - pub(crate) fn has_leading_comments(&self, node: T) -> bool + pub(crate) fn has_leading(&self, node: T) -> bool where T: Into>, { - !self.leading_comments(node).is_empty() + !self.leading(node).is_empty() } /// Returns the `node`'s [leading comments](self#leading-comments). #[inline] - pub(crate) fn leading_comments(&self, node: T) -> &[SourceComment] + pub(crate) fn leading(&self, node: T) -> &[SourceComment] where T: Into>, { @@ -299,15 +351,15 @@ impl<'a> Comments<'a> { } /// Returns `true` if node has any [dangling comments](self#dangling-comments). - pub(crate) fn has_dangling_comments(&self, node: T) -> bool + pub(crate) fn has_dangling(&self, node: T) -> bool where T: Into>, { - !self.dangling_comments(node).is_empty() + !self.dangling(node).is_empty() } /// Returns the [dangling comments](self#dangling-comments) of `node` - pub(crate) fn dangling_comments(&self, node: T) -> &[SourceComment] + pub(crate) fn dangling(&self, node: T) -> &[SourceComment] where T: Into>, { @@ -318,7 +370,7 @@ impl<'a> Comments<'a> { /// Returns the `node`'s [trailing comments](self#trailing-comments). #[inline] - pub(crate) fn trailing_comments(&self, node: T) -> &[SourceComment] + pub(crate) fn trailing(&self, node: T) -> &[SourceComment] where T: Into>, { @@ -329,57 +381,49 @@ impl<'a> Comments<'a> { /// Returns `true` if the given `node` has any [trailing comments](self#trailing-comments). #[inline] - pub(crate) fn has_trailing_comments(&self, node: T) -> bool + pub(crate) fn has_trailing(&self, node: T) -> bool where T: Into>, { - !self.trailing_comments(node).is_empty() + !self.trailing(node).is_empty() } /// Returns `true` if the given `node` has any [trailing own line comments](self#trailing-comments). #[inline] - pub(crate) fn has_trailing_own_line_comments(&self, node: T) -> bool + pub(crate) fn has_trailing_own_line(&self, node: T) -> bool where T: Into>, { - self.trailing_comments(node) + self.trailing(node) .iter() .any(|comment| comment.line_position().is_own_line()) } /// Returns an iterator over the [leading](self#leading-comments) and [trailing comments](self#trailing-comments) of `node`. - pub(crate) fn leading_trailing_comments( - &self, - node: T, - ) -> impl Iterator + pub(crate) fn leading_trailing(&self, node: T) -> impl Iterator where T: Into>, { - let node = node.into(); - self.leading_comments(node) - .iter() - .chain(self.trailing_comments(node).iter()) + let comments = self.leading_dangling_trailing(node); + comments.leading.iter().chain(comments.trailing) } /// Returns an iterator over the [leading](self#leading-comments), [dangling](self#dangling-comments), and [trailing](self#trailing) comments of `node`. - pub(crate) fn leading_dangling_trailing_comments( - &self, - node: T, - ) -> impl Iterator + pub(crate) fn leading_dangling_trailing(&self, node: T) -> LeadingDanglingTrailingComments where T: Into>, { self.data .comments - .parts(&NodeRefEqualityKey::from_ref(node.into())) + .leading_dangling_trailing(&NodeRefEqualityKey::from_ref(node.into())) } #[inline(always)] #[cfg(not(debug_assertions))] - pub(crate) fn assert_formatted_all_comments(&self, _source_code: SourceCode) {} + pub(crate) fn assert_all_formatted(&self, _source_code: SourceCode) {} #[cfg(debug_assertions)] - pub(crate) fn assert_formatted_all_comments(&self, source_code: SourceCode) { + pub(crate) fn assert_all_formatted(&self, source_code: SourceCode) { use std::fmt::Write; let mut output = String::new(); @@ -400,17 +444,49 @@ impl<'a> Comments<'a> { ); } + #[inline(always)] + #[cfg(not(debug_assertions))] + pub(crate) fn mark_verbatim_node_comments_formatted(&self, _node: AnyNodeRef) {} + + /// Marks the comments of a node printed in verbatim (suppressed) as formatted. + /// + /// Marks the dangling comments and the comments of all descendants as formatted. + /// The leading and trailing comments are not marked as formatted because they are formatted + /// normally if `node` is the first or last node of a suppression range. + #[cfg(debug_assertions)] + pub(crate) fn mark_verbatim_node_comments_formatted(&self, node: AnyNodeRef) { + for dangling in self.dangling(node) { + dangling.mark_formatted(); + } + + node.visit_preorder(&mut MarkVerbatimCommentsAsFormattedVisitor(self)); + } + /// Returns an object that implements [Debug] for nicely printing the [`Comments`]. pub(crate) fn debug(&'a self, source_code: SourceCode<'a>) -> DebugComments<'a> { DebugComments::new(&self.data.comments, source_code) } } +pub(crate) type LeadingDanglingTrailingComments<'a> = LeadingDanglingTrailing<'a, SourceComment>; + #[derive(Debug, Default)] struct CommentsData<'a> { comments: CommentsMap<'a>, } +struct MarkVerbatimCommentsAsFormattedVisitor<'a>(&'a Comments<'a>); + +impl<'a> PreorderVisitor<'a> for MarkVerbatimCommentsAsFormattedVisitor<'a> { + fn enter_node(&mut self, node: AnyNodeRef<'a>) -> TraversalSignal { + for comment in self.0.leading_dangling_trailing(node) { + comment.mark_formatted(); + } + + TraversalSignal::Traverse + } +} + #[cfg(test)] mod tests { use insta::assert_debug_snapshot; @@ -568,8 +644,13 @@ def test(x, y): def other(y, z): if y == z: pass - # Trailing `if` comment - # Trailing `other` function comment + # Trailing `pass` comment + # Trailing `if` statement comment + +class Test: + def func(): + pass + # Trailing `func` function comment test(10, 20) "#; diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 88388227ba0ab..eb7f189815b41 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -1,56 +1,197 @@ use std::cmp::Ordering; -use ruff_python_ast::{ - self as ast, Arguments, Comprehension, Expr, ExprAttribute, ExprBinOp, ExprIfExp, ExprSlice, - ExprStarred, MatchCase, Ranged, -}; -use ruff_text_size::TextRange; - use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::whitespace::indentation; +use ruff_python_ast::{self as ast, Comprehension, Expr, MatchCase, Parameters, Ranged}; use ruff_python_trivia::{ - indentation_at_offset, PythonWhitespace, SimpleToken, SimpleTokenKind, SimpleTokenizer, + find_only_token_in_range, indentation_at_offset, SimpleToken, SimpleTokenKind, SimpleTokenizer, }; -use ruff_source_file::{Locator, UniversalNewlines}; +use ruff_source_file::Locator; +use ruff_text_size::{TextLen, TextRange}; use crate::comments::visitor::{CommentPlacement, DecoratedComment}; use crate::expression::expr_slice::{assign_comment_in_slice, ExprSliceCommentSection}; -use crate::other::arguments::{ - assign_argument_separator_comment_placement, find_argument_separators, +use crate::expression::expr_tuple::is_tuple_parenthesized; +use crate::other::parameters::{ + assign_argument_separator_comment_placement, find_parameter_separators, }; +use crate::pattern::pattern_match_sequence::SequenceType; /// Manually attach comments to nodes that the default placement gets wrong. pub(super) fn place_comment<'a>( comment: DecoratedComment<'a>, locator: &Locator, ) -> CommentPlacement<'a> { - // Handle comments before and after bodies such as the different branches of an if statement - let comment = if comment.line_position().is_own_line() { - match handle_own_line_comment_after_body(comment, locator) { - CommentPlacement::Default(comment) => comment, - placement => { - return placement; - } + handle_parenthesized_comment(comment, locator) + .or_else(|comment| handle_end_of_line_comment_around_body(comment, locator)) + .or_else(|comment| handle_own_line_comment_around_body(comment, locator)) + .or_else(|comment| handle_enclosed_comment(comment, locator)) +} + +/// Handle parenthesized comments. A parenthesized comment is a comment that appears within a +/// parenthesis, but not within the range of the expression enclosed by the parenthesis. +/// For example, the comment here is a parenthesized comment: +/// ```python +/// if ( +/// # comment +/// True +/// ): +/// ... +/// ``` +/// The parentheses enclose `True`, but the range of `True`doesn't include the `# comment`. +/// +/// Default handling can get parenthesized comments wrong in a number of ways. For example, the +/// comment here is marked (by default) as a trailing comment of `x`, when it should be a leading +/// comment of `y`: +/// ```python +/// assert ( +/// x +/// ), ( # comment +/// y +/// ) +/// ``` +/// +/// Similarly, this is marked as a leading comment of `y`, when it should be a trailing comment of +/// `x`: +/// ```python +/// if ( +/// x +/// # comment +/// ): +/// y +/// ``` +/// +/// As a generalized solution, if a comment has a preceding node and a following node, we search for +/// opening and closing parentheses between the two nodes. If we find a closing parenthesis between +/// the preceding node and the comment, then the comment is a trailing comment of the preceding +/// node. If we find an opening parenthesis between the comment and the following node, then the +/// comment is a leading comment of the following node. +fn handle_parenthesized_comment<'a>( + comment: DecoratedComment<'a>, + locator: &Locator, +) -> CommentPlacement<'a> { + let Some(preceding) = comment.preceding_node() else { + return CommentPlacement::Default(comment); + }; + + let Some(following) = comment.following_node() else { + return CommentPlacement::Default(comment); + }; + + // TODO(charlie): Assert that there are no bogus tokens in these ranges. There are a few cases + // where we _can_ hit bogus tokens, but the parentheses need to come before them. For example: + // ```python + // try: + // some_call() + // except ( + // UnformattedError + // # trailing comment + // ) as err: + // handle_exception() + // ``` + // Here, we lex from the end of `UnformattedError` to the start of `handle_exception()`, which + // means we hit an "other" token at `err`. We know the parentheses must precede the `err`, but + // this could be fixed by including `as err` in the node range. + // + // Another example: + // ```python + // @deco + // # comment + // def decorated(): + // pass + // ``` + // Here, we lex from the end of `deco` to the start of the arguments of `decorated`. We hit an + // "other" token at `decorated`, but any parentheses must precede that. + // + // For now, we _can_ assert, but to do so, we stop lexing when we hit a token that precedes an + // identifier. + if comment.line_position().is_end_of_line() { + let tokenizer = SimpleTokenizer::new( + locator.contents(), + TextRange::new(preceding.end(), comment.start()), + ); + if tokenizer + .skip_trivia() + .take_while(|token| { + !matches!( + token.kind, + SimpleTokenKind::As | SimpleTokenKind::Def | SimpleTokenKind::Class + ) + }) + .any(|token| { + debug_assert!( + !matches!(token.kind, SimpleTokenKind::Bogus), + "Unexpected token between nodes: `{:?}`", + locator.slice(TextRange::new(preceding.end(), comment.start()),) + ); + + token.kind() == SimpleTokenKind::LParen + }) + { + return CommentPlacement::leading(following, comment); } } else { - match handle_end_of_line_comment_around_body(comment, locator) { - CommentPlacement::Default(comment) => comment, - placement => { - return placement; - } + let tokenizer = SimpleTokenizer::new( + locator.contents(), + TextRange::new(comment.end(), following.start()), + ); + if tokenizer + .skip_trivia() + .take_while(|token| { + !matches!( + token.kind, + SimpleTokenKind::As | SimpleTokenKind::Def | SimpleTokenKind::Class + ) + }) + .any(|token| { + debug_assert!( + !matches!(token.kind, SimpleTokenKind::Bogus), + "Unexpected token between nodes: `{:?}`", + locator.slice(TextRange::new(comment.end(), following.start())) + ); + token.kind() == SimpleTokenKind::RParen + }) + { + return CommentPlacement::trailing(preceding, comment); } - }; + } - // Change comment placement depending on the node type. These can be seen as node-specific - // fixups. + CommentPlacement::Default(comment) +} + +/// Handle a comment that is enclosed by a node. +fn handle_enclosed_comment<'a>( + comment: DecoratedComment<'a>, + locator: &Locator, +) -> CommentPlacement<'a> { match comment.enclosing_node() { - AnyNodeRef::Arguments(arguments) => { - handle_arguments_separator_comment(comment, arguments, locator) + AnyNodeRef::Parameters(parameters) => { + handle_parameters_separator_comment(comment, parameters, locator).or_else(|comment| { + if are_parameters_parenthesized(parameters, locator.contents()) { + handle_bracketed_end_of_line_comment(comment, locator) + } else { + CommentPlacement::Default(comment) + } + }) + } + AnyNodeRef::Arguments(_) | AnyNodeRef::TypeParams(_) => { + handle_bracketed_end_of_line_comment(comment, locator) } AnyNodeRef::Comprehension(comprehension) => { handle_comprehension_comment(comment, comprehension, locator) } - AnyNodeRef::ExprAttribute(attribute) => handle_attribute_comment(comment, attribute), + AnyNodeRef::PatternMatchSequence(pattern_match_sequence) => { + if SequenceType::from_pattern(pattern_match_sequence, locator.contents()) + .is_parenthesized() + { + handle_bracketed_end_of_line_comment(comment, locator) + } else { + CommentPlacement::Default(comment) + } + } + AnyNodeRef::ExprAttribute(attribute) => { + handle_attribute_comment(comment, attribute, locator) + } AnyNodeRef::ExprBinOp(binary_expression) => { handle_trailing_binary_expression_left_or_operator_comment( comment, @@ -58,13 +199,14 @@ pub(super) fn place_comment<'a>( locator, ) } - AnyNodeRef::ExprDict(_) | AnyNodeRef::Keyword(_) => { - handle_dict_unpacking_comment(comment, locator) - } + AnyNodeRef::Keyword(_) => handle_dict_unpacking_comment(comment, locator), + AnyNodeRef::ExprNamedExpr(_) => handle_named_expr_comment(comment, locator), + AnyNodeRef::ExprDict(_) => handle_dict_unpacking_comment(comment, locator) + .or_else(|comment| handle_bracketed_end_of_line_comment(comment, locator)), AnyNodeRef::ExprIfExp(expr_if) => handle_expr_if_comment(comment, expr_if, locator), AnyNodeRef::ExprSlice(expr_slice) => handle_slice_comments(comment, expr_slice, locator), AnyNodeRef::ExprStarred(starred) => { - handle_trailing_expression_starred_star_end_of_line_comment(comment, starred) + handle_trailing_expression_starred_star_end_of_line_comment(comment, starred, locator) } AnyNodeRef::ExprSubscript(expr_subscript) => { if let Expr::Slice(expr_slice) = expr_subscript.slice.as_ref() { @@ -73,22 +215,53 @@ pub(super) fn place_comment<'a>( CommentPlacement::Default(comment) } } - AnyNodeRef::MatchCase(match_case) => handle_match_comment(comment, match_case, locator), AnyNodeRef::ModModule(_) => { handle_module_level_own_line_comment_before_class_or_function_comment(comment, locator) } AnyNodeRef::WithItem(_) => handle_with_item_comment(comment, locator), - AnyNodeRef::StmtFunctionDef(_) | AnyNodeRef::StmtAsyncFunctionDef(_) => { - handle_leading_function_with_decorators_comment(comment) + AnyNodeRef::PatternMatchAs(_) => handle_pattern_match_as_comment(comment, locator), + AnyNodeRef::PatternMatchStar(_) => handle_pattern_match_star_comment(comment), + AnyNodeRef::PatternMatchMapping(pattern) => { + handle_bracketed_end_of_line_comment(comment, locator) + .or_else(|comment| handle_pattern_match_mapping_comment(comment, pattern, locator)) + } + AnyNodeRef::StmtFunctionDef(_) => handle_leading_function_with_decorators_comment(comment), + AnyNodeRef::StmtClassDef(class_def) => { + handle_leading_class_with_decorators_comment(comment, class_def) + } + AnyNodeRef::StmtImportFrom(import_from) => handle_import_from_comment(comment, import_from), + AnyNodeRef::StmtWith(with_) => handle_with_comment(comment, with_), + AnyNodeRef::ExprCall(_) => handle_call_comment(comment), + AnyNodeRef::ExprConstant(_) => { + if let Some(AnyNodeRef::ExprFString(fstring)) = comment.enclosing_parent() { + CommentPlacement::dangling(fstring, comment) + } else { + CommentPlacement::Default(comment) + } + } + AnyNodeRef::ExprFString(fstring) => CommentPlacement::dangling(fstring, comment), + AnyNodeRef::ExprList(_) + | AnyNodeRef::ExprSet(_) + | AnyNodeRef::ExprGeneratorExp(_) + | AnyNodeRef::ExprListComp(_) + | AnyNodeRef::ExprSetComp(_) + | AnyNodeRef::ExprDictComp(_) => handle_bracketed_end_of_line_comment(comment, locator), + AnyNodeRef::ExprTuple(tuple) if is_tuple_parenthesized(tuple, locator.contents()) => { + handle_bracketed_end_of_line_comment(comment, locator) } _ => CommentPlacement::Default(comment), } } +/// Handle an end-of-line comment around a body. fn handle_end_of_line_comment_around_body<'a>( comment: DecoratedComment<'a>, locator: &Locator, ) -> CommentPlacement<'a> { + if comment.line_position().is_own_line() { + return CommentPlacement::Default(comment); + } + // Handle comments before the first statement in a body // ```python // for x in range(10): # in the main body ... @@ -178,7 +351,6 @@ fn handle_end_of_line_comment_around_body<'a>( fn is_first_statement_in_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bool { match has_body { AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) - | AnyNodeRef::StmtAsyncFor(ast::StmtAsyncFor { body, orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { are_same_optional(statement, body.first()) || are_same_optional(statement, orelse.first()) @@ -189,12 +361,6 @@ fn is_first_statement_in_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bo orelse, finalbody, .. - }) - | AnyNodeRef::StmtTryStar(ast::StmtTryStar { - body, - orelse, - finalbody, - .. }) => { are_same_optional(statement, body.first()) || are_same_optional(statement, orelse.first()) @@ -207,17 +373,23 @@ fn is_first_statement_in_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bo | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) + | AnyNodeRef::MatchCase(MatchCase { body, .. }) | AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) - | AnyNodeRef::StmtAsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) => { are_same_optional(statement, body.first()) } + AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => { + are_same_optional(statement, cases.first()) + } + _ => false, } } -/// Handles own line comments after a body, either at the end or between bodies. +/// Handles own-line comments around a body (at the end of the body, at the end of the header +/// preceding the body, or between bodies): +/// /// ```python /// for x in y: /// pass @@ -227,12 +399,20 @@ fn is_first_statement_in_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bo /// print("I have no comments") /// # This should be a trailing comment of the print /// # This is a trailing comment of the entire statement +/// +/// if ( +/// True +/// # This should be a trailing comment of `True` and not a leading comment of `pass` +/// ): +/// pass /// ``` -fn handle_own_line_comment_after_body<'a>( +fn handle_own_line_comment_around_body<'a>( comment: DecoratedComment<'a>, locator: &Locator, ) -> CommentPlacement<'a> { - debug_assert!(comment.line_position().is_own_line()); + if comment.line_position().is_end_of_line() { + return CommentPlacement::Default(comment); + } // If the following is the first child in an alternative body, this must be the last child in // the previous one @@ -260,16 +440,12 @@ fn handle_own_line_comment_after_body<'a>( return CommentPlacement::Default(comment); } - // Check if we're between bodies and should attach to the following body. If that is not the - // case, either because there is no following branch or because the indentation is too deep, - // attach to the recursively last statement in the preceding body with the matching indentation. - match handle_own_line_comment_between_branches(comment, preceding, locator) { - CommentPlacement::Default(comment) => { - // Knowing the comment is not between branches, handle comments after the last branch - handle_own_line_comment_after_branch(comment, preceding, locator) - } - placement => placement, - } + // Check if we're between bodies and should attach to the following body. + handle_own_line_comment_between_branches(comment, preceding, locator).or_else(|comment| { + // Otherwise, there's no following branch or the indentation is too deep, so attach to the + // recursively last statement in the preceding body with the matching indentation. + handle_own_line_comment_after_branch(comment, preceding, locator) + }) } /// Handles own line comments between two branches of a node. @@ -297,7 +473,7 @@ fn handle_own_line_comment_between_branches<'a>( // It depends on the indentation level of the comment if it is a leading comment for the // following branch or if it a trailing comment of the previous body's last statement. - let comment_indentation = indentation_at_offset(comment.slice().range().start(), locator) + let comment_indentation = indentation_at_offset(comment.slice().start(), locator) .unwrap_or_default() .len(); @@ -369,105 +545,6 @@ fn handle_own_line_comment_between_branches<'a>( } } -/// Handles leading comments in front of a match case or a trailing comment of the `match` statement. -/// ```python -/// match pt: -/// # Leading `case(x, y)` comment -/// case (x, y): -/// return Point3d(x, y, 0) -/// # Leading `case (x, y, z)` comment -/// case _: -/// ``` -fn handle_match_comment<'a>( - comment: DecoratedComment<'a>, - match_case: &'a MatchCase, - locator: &Locator, -) -> CommentPlacement<'a> { - // Must be an own line comment after the last statement in a match case - if comment.line_position().is_end_of_line() || comment.following_node().is_some() { - return CommentPlacement::Default(comment); - } - - // And its parent match statement. - let Some(match_stmt) = comment.enclosing_parent().and_then(AnyNodeRef::stmt_match) else { - return CommentPlacement::Default(comment); - }; - - // Get the next sibling (sibling traversal would be really nice) - let current_case_index = match_stmt - .cases - .iter() - .position(|case| case == match_case) - .expect("Expected case to belong to parent match statement."); - - let next_case = match_stmt.cases.get(current_case_index + 1); - - let comment_indentation = indentation_at_offset(comment.slice().range().start(), locator) - .unwrap_or_default() - .len(); - let match_case_indentation = indentation(locator, match_case).unwrap().len(); - - if let Some(next_case) = next_case { - // The comment's indentation is less or equal to the `case` indention and there's a following - // `case` arm. - // ```python - // match pt: - // case (x, y): - // return Point3d(x, y, 0) - // # Leading `case (x, y, z)` comment - // case _: - // pass - // ``` - // Attach the `comment` as leading comment to the next case. - if comment_indentation <= match_case_indentation { - CommentPlacement::leading(next_case, comment) - } else { - // Otherwise, delegate to `handle_trailing_body_comment` - // ```python - // match pt: - // case (x, y): - // return Point3d(x, y, 0) - // # Trailing case body comment - // case _: - // pass - // ``` - CommentPlacement::Default(comment) - } - } else { - // Comment after the last statement in a match case... - let match_stmt_indentation = indentation(locator, match_stmt).unwrap_or_default().len(); - - if comment_indentation <= match_case_indentation - && comment_indentation > match_stmt_indentation - { - // The comment's indent matches the `case` indent (or is larger than the `match`'s indent). - // ```python - // match pt: - // case (x, y): - // return Point3d(x, y, 0) - // case _: - // pass - // # Trailing match comment - // ``` - // This is a trailing comment of the last case. - CommentPlacement::trailing(match_case, comment) - } else { - // Delegate to `handle_trailing_body_comment` because it's either a trailing indent - // for the last statement in the `case` body or a comment for the parent of the `match` - // - // ```python - // match pt: - // case (x, y): - // return Point3d(x, y, 0) - // case _: - // pass - // # trailing case comment - // ``` - CommentPlacement::Default(comment) - } - } -} - /// Determine where to attach an own line comment after a branch depending on its indentation fn handle_own_line_comment_after_branch<'a>( comment: DecoratedComment<'a>, @@ -480,7 +557,7 @@ fn handle_own_line_comment_after_branch<'a>( // We only care about the length because indentations with mixed spaces and tabs are only valid if // the indent-level doesn't depend on the tab width (the indent level must be the same if the tab width is 1 or 8). - let comment_indentation = indentation_at_offset(comment.slice().range().start(), locator) + let comment_indentation = indentation_at_offset(comment.slice().start(), locator) .unwrap_or_default() .len(); @@ -500,12 +577,11 @@ fn handle_own_line_comment_after_branch<'a>( return CommentPlacement::Default(comment); } - let mut parent_body = None; - let mut current_body = Some(preceding_node); - let mut last_child_in_current_body = last_child; + let mut parent = None; + let mut last_child_in_parent = last_child; loop { - let child_indentation = indentation(locator, &last_child_in_current_body) + let child_indentation = indentation(locator, &last_child_in_parent) .unwrap_or_default() .len(); @@ -514,15 +590,16 @@ fn handle_own_line_comment_after_branch<'a>( // if parent_body: // if current_body: // child_in_body() - // last_child_in_current_body # may or may not have children on its own + // last_child_in_current_body # may or may not have children on its own // # less: Comment belongs to the parent block. - // # less + // # less: Comment belongs to the parent block. // # equal: The comment belongs to this block. - // # greater - // # greater: The comment belongs to the inner block. + // # greater (but less in the next iteration) + // # greater: The comment belongs to the inner block. + // ``` match comment_indentation.cmp(&child_indentation) { Ordering::Less => { - return if let Some(parent_block) = parent_body { + return if let Some(parent_block) = parent { // Comment belongs to the parent block. CommentPlacement::trailing(parent_block, comment) } else { @@ -537,14 +614,13 @@ fn handle_own_line_comment_after_branch<'a>( } Ordering::Equal => { // The comment belongs to this block. - return CommentPlacement::trailing(last_child_in_current_body, comment); + return CommentPlacement::trailing(last_child_in_parent, comment); } Ordering::Greater => { - if let Some(nested_child) = last_child_in_body(last_child_in_current_body) { + if let Some(nested_child) = last_child_in_body(last_child_in_parent) { // The comment belongs to the inner block. - parent_body = current_body; - current_body = Some(last_child_in_current_body); - last_child_in_current_body = nested_child; + parent = Some(last_child_in_parent); + last_child_in_parent = nested_child; } else { // The comment is overindented, we assign it to the most indented child we have. // ```python @@ -552,23 +628,23 @@ fn handle_own_line_comment_after_branch<'a>( // pass // # comment // ``` - return CommentPlacement::trailing(last_child_in_current_body, comment); + return CommentPlacement::trailing(last_child_in_parent, comment); } } } } } -/// Attaches comments for the positional only arguments separator `/` or the keywords only arguments -/// separator `*` as dangling comments to the enclosing [`Arguments`] node. +/// Attaches comments for the positional-only parameters separator `/` or the keywords-only +/// parameters separator `*` as dangling comments to the enclosing [`Parameters`] node. /// /// See [`assign_argument_separator_comment_placement`] -fn handle_arguments_separator_comment<'a>( +fn handle_parameters_separator_comment<'a>( comment: DecoratedComment<'a>, - arguments: &Arguments, + parameters: &Parameters, locator: &Locator, ) -> CommentPlacement<'a> { - let (slash, star) = find_argument_separators(locator.contents(), arguments); + let (slash, star) = find_parameter_separators(locator.contents(), parameters); let comment_range = comment.slice().range(); let placement = assign_argument_separator_comment_placement( slash.as_ref(), @@ -596,7 +672,7 @@ fn handle_arguments_separator_comment<'a>( /// ``` fn handle_trailing_binary_expression_left_or_operator_comment<'a>( comment: DecoratedComment<'a>, - binary_expression: &'a ExprBinOp, + binary_expression: &'a ast::ExprBinOp, locator: &Locator, ) -> CommentPlacement<'a> { // Only if there's a preceding node (in which case, the preceding node is `left`). @@ -732,9 +808,7 @@ fn handle_module_level_own_line_comment_before_class_or_function_comment<'a>( // ... where the following is a function or class statement. if !matches!( following, - AnyNodeRef::StmtAsyncFunctionDef(_) - | AnyNodeRef::StmtFunctionDef(_) - | AnyNodeRef::StmtClassDef(_) + AnyNodeRef::StmtFunctionDef(_) | AnyNodeRef::StmtClassDef(_) ) { return CommentPlacement::Default(comment); } @@ -760,10 +834,10 @@ fn handle_module_level_own_line_comment_before_class_or_function_comment<'a>( /// ``` fn handle_slice_comments<'a>( comment: DecoratedComment<'a>, - expr_slice: &'a ExprSlice, + expr_slice: &'a ast::ExprSlice, locator: &Locator, ) -> CommentPlacement<'a> { - let ExprSlice { + let ast::ExprSlice { range: _, lower, upper, @@ -830,21 +904,47 @@ fn handle_slice_comments<'a>( fn handle_leading_function_with_decorators_comment(comment: DecoratedComment) -> CommentPlacement { let is_preceding_decorator = comment .preceding_node() - .map_or(false, |node| node.is_decorator()); + .is_some_and(|node| node.is_decorator()); - let is_following_arguments = comment + let is_following_parameters = comment .following_node() - .map_or(false, |node| node.is_arguments()); + .is_some_and(|node| node.is_parameters()); - if comment.line_position().is_own_line() && is_preceding_decorator && is_following_arguments { + if comment.line_position().is_own_line() && is_preceding_decorator && is_following_parameters { CommentPlacement::dangling(comment.enclosing_node(), comment) } else { CommentPlacement::Default(comment) } } +/// Handle comments between decorators and the decorated node. +/// +/// For example, given: +/// ```python +/// @dataclass +/// # comment +/// class Foo(Bar): +/// ... +/// ``` +/// +/// The comment should be attached to the enclosing [`ast::StmtClassDef`] as a dangling node, +/// as opposed to being treated as a leading comment on `Bar` or similar. +fn handle_leading_class_with_decorators_comment<'a>( + comment: DecoratedComment<'a>, + class_def: &'a ast::StmtClassDef, +) -> CommentPlacement<'a> { + if comment.line_position().is_own_line() && comment.start() < class_def.name.start() { + if let Some(decorator) = class_def.decorator_list.last() { + if decorator.end() < comment.start() { + return CommentPlacement::dangling(class_def, comment); + } + } + } + CommentPlacement::Default(comment) +} + /// Handles comments between `**` and the variable name in dict unpacking -/// It attaches these to the appropriate value node +/// It attaches these to the appropriate value node. /// /// ```python /// { @@ -882,36 +982,31 @@ fn handle_dict_unpacking_comment<'a>( // if the remaining tokens from the previous node are exactly `**`, // re-assign the comment to the one that follows the stars - let mut count = 0; - - // we start from the preceding node but we skip its token - if let Some(token) = tokens.next() { - // The Keyword case - if token.kind == SimpleTokenKind::Star { - count += 1; - } else { - // The dict case - debug_assert!( - matches!( - token, - SimpleToken { - kind: SimpleTokenKind::LBrace - | SimpleTokenKind::Comma - | SimpleTokenKind::Colon, - .. - } - ), - "{token:?}", - ); - } + if tokens.any(|token| token.kind == SimpleTokenKind::DoubleStar) { + CommentPlacement::trailing(following, comment) + } else { + CommentPlacement::Default(comment) } +} - for token in tokens { - debug_assert!(token.kind == SimpleTokenKind::Star, "Expected star token"); - count += 1; - } - if count == 2 { - return CommentPlacement::trailing(following, comment); +/// Handle comments between a function call and its arguments. For example, attach the following as +/// dangling on the call: +/// ```python +/// ( +/// func +/// # dangling +/// () +/// ) +/// ``` +fn handle_call_comment(comment: DecoratedComment) -> CommentPlacement { + if comment.line_position().is_own_line() { + if comment.preceding_node().is_some_and(|preceding| { + comment.following_node().is_some_and(|following| { + preceding.end() < comment.start() && comment.end() < following.start() + }) + }) { + return CommentPlacement::dangling(comment.enclosing_node(), comment); + } } CommentPlacement::Default(comment) @@ -920,43 +1015,88 @@ fn handle_dict_unpacking_comment<'a>( /// Own line comments coming after the node are always dangling comments /// ```python /// ( -/// a -/// # trailing a comment -/// . # dangling comment -/// # or this +/// a # trailing comment on `a` +/// # dangling comment on the attribute +/// . # dangling comment on the attribute +/// # dangling comment on the attribute /// b /// ) /// ``` fn handle_attribute_comment<'a>( comment: DecoratedComment<'a>, - attribute: &'a ExprAttribute, + attribute: &'a ast::ExprAttribute, + locator: &Locator, ) -> CommentPlacement<'a> { - debug_assert!( - comment.preceding_node().is_some(), - "The enclosing node an attribute expression, expected to be at least after the name" - ); + if comment.preceding_node().is_none() { + // ```text + // ( value) . attr + // ^^^^ we're in this range + // ``` + return CommentPlacement::leading(attribute.value.as_ref(), comment); + } - // ```text - // value . attr - // ^^^^^^^ we're in this range + // If the comment is parenthesized, use the parentheses to either attach it as a trailing + // comment on the value or a dangling comment on the attribute. + // For example, treat this as trailing: + // ```python + // ( + // ( + // value + // # comment + // ) + // .attribute + // ) + // ``` + // + // However, treat this as dangling: + // ```python + // ( + // (value) + // # comment + // .attribute + // ) + // ``` + if let Some(right_paren) = SimpleTokenizer::starts_at(attribute.value.end(), locator.contents()) + .skip_trivia() + .take_while(|token| token.kind == SimpleTokenKind::RParen) + .last() + { + return if comment.start() < right_paren.start() { + CommentPlacement::trailing(attribute.value.as_ref(), comment) + } else { + CommentPlacement::dangling(comment.enclosing_node(), comment) + }; + } + + // If the comment precedes the `.`, treat it as trailing _if_ it's on the same line as the + // value. For example, treat this as trailing: + // ```python + // ( + // value # comment + // .attribute + // ) + // ``` + // + // However, treat this as dangling: + // ```python + // ( + // value + // # comment + // .attribute + // ) // ``` - debug_assert!( - TextRange::new(attribute.value.end(), attribute.attr.start()) - .contains(comment.slice().start()) - ); if comment.line_position().is_end_of_line() { - // Attach to node with b - // ```python - // x322 = ( - // a - // . # end-of-line dot comment 2 - // b - // ) - // ``` - CommentPlacement::trailing(comment.enclosing_node(), comment) - } else { - CommentPlacement::dangling(attribute, comment) + let dot_token = find_only_token_in_range( + TextRange::new(attribute.value.end(), attribute.attr.start()), + SimpleTokenKind::Dot, + locator.contents(), + ); + if comment.end() < dot_token.start() { + return CommentPlacement::trailing(attribute.value.as_ref(), comment); + } } + + CommentPlacement::dangling(comment.enclosing_node(), comment) } /// Assign comments between `if` and `test` and `else` and `orelse` as leading to the respective @@ -976,10 +1116,10 @@ fn handle_attribute_comment<'a>( /// happens if the comments are in a weird position but it also doesn't hurt handling it. fn handle_expr_if_comment<'a>( comment: DecoratedComment<'a>, - expr_if: &'a ExprIfExp, + expr_if: &'a ast::ExprIfExp, locator: &Locator, ) -> CommentPlacement<'a> { - let ExprIfExp { + let ast::ExprIfExp { range: _, test, body, @@ -993,7 +1133,7 @@ fn handle_expr_if_comment<'a>( let if_token = find_only_token_in_range( TextRange::new(body.end(), test.start()), SimpleTokenKind::If, - locator, + locator.contents(), ); // Between `if` and `test` if if_token.range.start() < comment.slice().start() && comment.slice().start() < test.start() { @@ -1003,7 +1143,7 @@ fn handle_expr_if_comment<'a>( let else_token = find_only_token_in_range( TextRange::new(test.end(), orelse.start()), SimpleTokenKind::Else, - locator, + locator.contents(), ); // Between `else` and `orelse` if else_token.range.start() < comment.slice().start() @@ -1015,35 +1155,37 @@ fn handle_expr_if_comment<'a>( CommentPlacement::Default(comment) } -/// Moving -/// ``` python -/// call( -/// # Leading starred comment -/// * # Trailing star comment -/// [] -/// ) -/// ``` -/// to +/// Handles trailing comments on between the `*` of a starred expression and the +/// expression itself. For example, attaches the first two comments here as leading +/// comments on the enclosing node, and the third to the `True` node. /// ``` python /// call( -/// # Leading starred comment -/// # Trailing star comment -/// * [] +/// * # dangling end-of-line comment +/// # dangling own line comment +/// ( # leading comment on the expression +/// True +/// ) /// ) /// ``` fn handle_trailing_expression_starred_star_end_of_line_comment<'a>( comment: DecoratedComment<'a>, - starred: &'a ExprStarred, + starred: &'a ast::ExprStarred, + locator: &Locator, ) -> CommentPlacement<'a> { - if comment.line_position().is_own_line() { - return CommentPlacement::Default(comment); - } - - if comment.following_node().is_none() { - return CommentPlacement::Default(comment); + if comment.following_node().is_some() { + let tokenizer = SimpleTokenizer::new( + locator.contents(), + TextRange::new(starred.start(), comment.start()), + ); + if !tokenizer + .skip_trivia() + .any(|token| token.kind() == SimpleTokenKind::LParen) + { + return CommentPlacement::leading(starred, comment); + } } - CommentPlacement::leading(starred, comment) + CommentPlacement::Default(comment) } /// Handles trailing own line comments before the `as` keyword of a with item and @@ -1055,7 +1197,7 @@ fn handle_trailing_expression_starred_star_end_of_line_comment<'a>( /// # trailing a own line comment /// as # trailing as same line comment /// b -// ): ... +/// ): ... /// ``` fn handle_with_item_comment<'a>( comment: DecoratedComment<'a>, @@ -1073,54 +1215,315 @@ fn handle_with_item_comment<'a>( let as_token = find_only_token_in_range( TextRange::new(context_expr.end(), optional_vars.start()), SimpleTokenKind::As, - locator, + locator.contents(), ); if comment.end() < as_token.start() { // If before the `as` keyword, then it must be a trailing comment of the context expression. CommentPlacement::trailing(context_expr, comment) - } - // Trailing end of line comment coming after the `as` keyword`. - else if comment.line_position().is_end_of_line() { + } else if comment.line_position().is_end_of_line() { + // Trailing end of line comment coming after the `as` keyword`. CommentPlacement::dangling(comment.enclosing_node(), comment) } else { CommentPlacement::leading(optional_vars, comment) } } -/// Looks for a token in the range that contains no other tokens except for parentheses outside -/// the expression ranges -fn find_only_token_in_range( - range: TextRange, - token_kind: SimpleTokenKind, +/// Handles trailing comments after the `as` keyword of a pattern match item: +/// +/// ```python +/// case ( +/// pattern +/// as # dangling end of line comment +/// # dangling own line comment +/// name +/// ): ... +/// ``` +fn handle_pattern_match_as_comment<'a>( + comment: DecoratedComment<'a>, locator: &Locator, -) -> SimpleToken { - let mut tokens = SimpleTokenizer::new(locator.contents(), range) +) -> CommentPlacement<'a> { + debug_assert!(comment.enclosing_node().is_pattern_match_as()); + + let Some(pattern) = comment.preceding_node() else { + return CommentPlacement::Default(comment); + }; + + let mut tokens = SimpleTokenizer::starts_at(pattern.end(), locator.contents()) .skip_trivia() .skip_while(|token| token.kind == SimpleTokenKind::RParen); - let token = tokens.next().expect("Expected a token"); - debug_assert_eq!(token.kind(), token_kind); - let mut tokens = tokens.skip_while(|token| token.kind == SimpleTokenKind::LParen); - debug_assert_eq!(tokens.next(), None); - token + + let Some(as_token) = tokens + .next() + .filter(|token| token.kind == SimpleTokenKind::As) + else { + return CommentPlacement::Default(comment); + }; + + if comment.end() < as_token.start() { + // If before the `as` keyword, then it must be a trailing comment of the pattern. + CommentPlacement::trailing(pattern, comment) + } else { + // Otherwise, must be a dangling comment. (Any comments that follow the name will be + // trailing comments on the pattern match item, rather than enclosed by it.) + CommentPlacement::dangling(comment.enclosing_node(), comment) + } +} + +/// Handles dangling comments between the `*` token and identifier of a pattern match star: +/// +/// ```python +/// case [ +/// ..., +/// * # dangling end of line comment +/// # dangling end of line comment +/// rest, +/// ]: ... +/// ``` +fn handle_pattern_match_star_comment(comment: DecoratedComment) -> CommentPlacement { + CommentPlacement::dangling(comment.enclosing_node(), comment) +} + +/// Handles trailing comments after the `**` in a pattern match item. The comments can either +/// appear between the `**` and the identifier, or after the identifier (which is just an +/// identifier, not a node). +/// +/// ```python +/// case { +/// ** # dangling end of line comment +/// # dangling own line comment +/// rest # dangling end of line comment +/// # dangling own line comment +/// ): ... +/// ``` +fn handle_pattern_match_mapping_comment<'a>( + comment: DecoratedComment<'a>, + pattern: &'a ast::PatternMatchMapping, + locator: &Locator, +) -> CommentPlacement<'a> { + // The `**` has to come at the end, so there can't be another node after it. (The identifier, + // like `rest` above, isn't a node.) + if comment.following_node().is_some() { + return CommentPlacement::Default(comment); + }; + + // If there's no rest pattern, no need to do anything special. + let Some(rest) = pattern.rest.as_ref() else { + return CommentPlacement::Default(comment); + }; + + // If the comment falls after the `**rest` entirely, treat it as dangling on the enclosing + // node. + if comment.start() > rest.end() { + return CommentPlacement::dangling(comment.enclosing_node(), comment); + } + + // Look at the tokens between the previous node (or the start of the pattern) and the comment. + let preceding_end = match comment.preceding_node() { + Some(preceding) => preceding.end(), + None => comment.enclosing_node().start(), + }; + let mut tokens = SimpleTokenizer::new( + locator.contents(), + TextRange::new(preceding_end, comment.start()), + ) + .skip_trivia(); + + // If the remaining tokens from the previous node include `**`, mark as a dangling comment. + if tokens.any(|token| token.kind == SimpleTokenKind::DoubleStar) { + CommentPlacement::dangling(comment.enclosing_node(), comment) + } else { + CommentPlacement::Default(comment) + } +} + +/// Handles comments around the `:=` token in a named expression (walrus operator). +/// +/// For example, here, `# 1` and `# 2` will be marked as dangling comments on the named expression, +/// while `# 3` and `4` will be attached `y` (via our general parenthesized comment handling), and +/// `# 5` will be a trailing comment on the named expression. +/// +/// ```python +/// if ( +/// x +/// := # 1 +/// # 2 +/// ( # 3 +/// y # 4 +/// ) # 5 +/// ): +/// pass +/// ``` +fn handle_named_expr_comment<'a>( + comment: DecoratedComment<'a>, + locator: &Locator, +) -> CommentPlacement<'a> { + debug_assert!(comment.enclosing_node().is_expr_named_expr()); + + let (Some(target), Some(value)) = (comment.preceding_node(), comment.following_node()) else { + return CommentPlacement::Default(comment); + }; + + let colon_equal = find_only_token_in_range( + TextRange::new(target.end(), value.start()), + SimpleTokenKind::ColonEqual, + locator.contents(), + ); + + if comment.end() < colon_equal.start() { + // If the comment is before the `:=` token, then it must be a trailing comment of the + // target. + CommentPlacement::trailing(target, comment) + } else { + // Otherwise, treat it as dangling. We effectively treat it as a comment on the `:=` itself. + CommentPlacement::dangling(comment.enclosing_node(), comment) + } +} + +/// Attach an end-of-line comment immediately following an open bracket as a dangling comment on +/// enclosing node. +/// +/// For example, given the following function call: +/// ```python +/// foo( # comment +/// bar, +/// ) +/// ``` +/// +/// The comment will be attached to the [`Arguments`] node as a dangling comment, to ensure +/// that it remains on the same line as open parenthesis. +/// +/// Similarly, given: +/// ```python +/// type foo[ # comment +/// bar, +/// ] = ... +/// ``` +/// +/// The comment will be attached to the [`TypeParams`] node as a dangling comment, to ensure +/// that it remains on the same line as open bracket. +fn handle_bracketed_end_of_line_comment<'a>( + comment: DecoratedComment<'a>, + locator: &Locator, +) -> CommentPlacement<'a> { + if comment.line_position().is_end_of_line() { + // Ensure that there are no tokens between the open bracket and the comment. + let mut lexer = SimpleTokenizer::new( + locator.contents(), + TextRange::new(comment.enclosing_node().start(), comment.start()), + ) + .skip_trivia(); + + // Skip the opening parenthesis. + let Some(paren) = lexer.next() else { + return CommentPlacement::Default(comment); + }; + debug_assert!(matches!( + paren.kind(), + SimpleTokenKind::LParen | SimpleTokenKind::LBrace | SimpleTokenKind::LBracket + )); + + // If there are no additional tokens between the open parenthesis and the comment, then + // it should be attached as a dangling comment on the brackets, rather than a leading + // comment on the first argument. + if lexer.next().is_none() { + return CommentPlacement::dangling(comment.enclosing_node(), comment); + } + } + + CommentPlacement::Default(comment) } -// Handle comments inside comprehensions, e.g. -// -// ```python -// [ -// a -// for # dangling on the comprehension -// b -// # dangling on the comprehension -// in # dangling on comprehension.iter -// # leading on the iter -// c -// # dangling on comprehension.if.n -// if # dangling on comprehension.if.n -// d -// ] -// ``` +/// Attach an enclosed end-of-line comment to a [`ast::StmtImportFrom`]. +/// +/// For example, given: +/// ```python +/// from foo import ( # comment +/// bar, +/// ) +/// ``` +/// +/// The comment will be attached to the [`ast::StmtImportFrom`] node as a dangling comment, to +/// ensure that it remains on the same line as the [`ast::StmtImportFrom`] itself. +fn handle_import_from_comment<'a>( + comment: DecoratedComment<'a>, + import_from: &'a ast::StmtImportFrom, +) -> CommentPlacement<'a> { + // The comment needs to be on the same line, but before the first member. For example, we want + // to treat this as a dangling comment: + // ```python + // from foo import ( # comment + // bar, + // baz, + // qux, + // ) + // ``` + // However, this should _not_ be treated as a dangling comment: + // ```python + // from foo import (bar, # comment + // baz, + // qux, + // ) + // ``` + // Thus, we check whether the comment is an end-of-line comment _between_ the start of the + // statement and the first member. If so, the only possible position is immediately following + // the open parenthesis. + if comment.line_position().is_end_of_line() + && import_from.names.first().is_some_and(|first_name| { + import_from.start() < comment.start() && comment.start() < first_name.start() + }) + { + CommentPlacement::dangling(comment.enclosing_node(), comment) + } else { + CommentPlacement::Default(comment) + } +} + +/// Attach an enclosed end-of-line comment to a [`ast::StmtWith`]. +/// +/// For example, given: +/// ```python +/// with ( # foo +/// CtxManager1() as example1, +/// CtxManager2() as example2, +/// CtxManager3() as example3, +/// ): +/// ... +/// ``` +/// +/// The comment will be attached to the [`ast::StmtWith`] node as a dangling comment, to ensure +/// that it remains on the same line as the [`ast::StmtWith`] itself. +fn handle_with_comment<'a>( + comment: DecoratedComment<'a>, + with_statement: &'a ast::StmtWith, +) -> CommentPlacement<'a> { + if comment.line_position().is_end_of_line() + && with_statement.items.first().is_some_and(|with_item| { + with_statement.start() < comment.start() && comment.start() < with_item.start() + }) + { + CommentPlacement::dangling(comment.enclosing_node(), comment) + } else { + CommentPlacement::Default(comment) + } +} + +/// Handle comments inside comprehensions, e.g. +/// +/// ```python +/// [ +/// a +/// for # dangling on the comprehension +/// b +/// # dangling on the comprehension +/// in # dangling on comprehension.iter +/// # leading on the iter +/// c +/// # dangling on comprehension.if.n +/// if # dangling on comprehension.if.n +/// d +/// ] +/// ``` fn handle_comprehension_comment<'a>( comment: DecoratedComment<'a>, comprehension: &'a Comprehension, @@ -1136,7 +1539,7 @@ fn handle_comprehension_comment<'a>( // b in c // ] // ``` - if comment.slice().end() < comprehension.target.range().start() { + if comment.slice().end() < comprehension.target.start() { return if is_own_line { // own line comments are correctly assigned as leading the target CommentPlacement::Default(comment) @@ -1147,12 +1550,9 @@ fn handle_comprehension_comment<'a>( } let in_token = find_only_token_in_range( - TextRange::new( - comprehension.target.range().end(), - comprehension.iter.range().start(), - ), + TextRange::new(comprehension.target.end(), comprehension.iter.start()), SimpleTokenKind::In, - locator, + locator.contents(), ); // Comments between the target and the `in` @@ -1183,7 +1583,7 @@ fn handle_comprehension_comment<'a>( // c // ] // ``` - if comment.slice().start() < comprehension.iter.range().start() { + if comment.slice().start() < comprehension.iter.start() { return if is_own_line { CommentPlacement::Default(comment) } else { @@ -1192,7 +1592,7 @@ fn handle_comprehension_comment<'a>( }; } - let mut last_end = comprehension.iter.range().end(); + let mut last_end = comprehension.iter.end(); for if_node in &comprehension.ifs { // ```python @@ -1213,20 +1613,20 @@ fn handle_comprehension_comment<'a>( // ] // ``` let if_token = find_only_token_in_range( - TextRange::new(last_end, if_node.range().start()), + TextRange::new(last_end, if_node.start()), SimpleTokenKind::If, - locator, + locator.contents(), ); if is_own_line { if last_end < comment.slice().start() && comment.slice().start() < if_token.start() { return CommentPlacement::dangling(if_node, comment); } } else if if_token.start() < comment.slice().start() - && comment.slice().start() < if_node.range().start() + && comment.slice().start() < if_node.start() { return CommentPlacement::dangling(if_node, comment); } - last_end = if_node.range().end(); + last_end = if_node.end(); } CommentPlacement::Default(comment) @@ -1237,18 +1637,16 @@ fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option) -> bool where T: Into>, { - right.map_or(false, |right| left.ptr_eq(right.into())) + right.is_some_and(|right| left.ptr_eq(right.into())) } -/// The last child of the last branch, if the node hs multiple branches. +/// The last child of the last branch, if the node has multiple branches. fn last_child_in_body(node: AnyNodeRef) -> Option { let body = match node { AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) - | AnyNodeRef::StmtAsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. }) | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) | AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) - | AnyNodeRef::StmtAsyncWith(ast::StmtAsyncWith { body, .. }) - | AnyNodeRef::MatchCase(ast::MatchCase { body, .. }) + | AnyNodeRef::MatchCase(MatchCase { body, .. }) | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) @@ -1260,7 +1658,6 @@ fn last_child_in_body(node: AnyNodeRef) -> Option { }) => elif_else_clauses.last().map_or(body, |clause| &clause.body), AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) - | AnyNodeRef::StmtAsyncFor(ast::StmtAsyncFor { body, orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { if orelse.is_empty() { body @@ -1279,13 +1676,6 @@ fn last_child_in_body(node: AnyNodeRef) -> Option { orelse, finalbody, .. - }) - | AnyNodeRef::StmtTryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - .. }) => { if finalbody.is_empty() { if orelse.is_empty() { @@ -1313,7 +1703,6 @@ fn last_child_in_body(node: AnyNodeRef) -> Option { fn is_first_statement_in_alternate_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bool { match has_body { AnyNodeRef::StmtFor(ast::StmtFor { orelse, .. }) - | AnyNodeRef::StmtAsyncFor(ast::StmtAsyncFor { orelse, .. }) | AnyNodeRef::StmtWhile(ast::StmtWhile { orelse, .. }) => { are_same_optional(statement, orelse.first()) } @@ -1323,12 +1712,6 @@ fn is_first_statement_in_alternate_body(statement: AnyNodeRef, has_body: AnyNode orelse, finalbody, .. - }) - | AnyNodeRef::StmtTryStar(ast::StmtTryStar { - handlers, - orelse, - finalbody, - .. }) => { are_same_optional(statement, handlers.first()) || are_same_optional(statement, orelse.first()) @@ -1342,21 +1725,39 @@ fn is_first_statement_in_alternate_body(statement: AnyNodeRef, has_body: AnyNode } } -/// Counts the number of newlines in `contents`. -fn max_empty_lines(contents: &str) -> usize { - let mut empty_lines = 0; - let mut max_empty_lines = 0; +/// Returns `true` if the parameters are parenthesized (as in a function definition), or `false` if +/// not (as in a lambda). +fn are_parameters_parenthesized(parameters: &Parameters, contents: &str) -> bool { + // A lambda never has parentheses around its parameters, but a function definition always does. + contents[parameters.range()].starts_with('(') +} - for line in contents.universal_newlines().skip(1) { - if line.trim_whitespace().is_empty() { - empty_lines += 1; - } else { - max_empty_lines = max_empty_lines.max(empty_lines); - empty_lines = 0; +/// Counts the number of empty lines in `contents`. +fn max_empty_lines(contents: &str) -> u32 { + let mut newlines = 0u32; + let mut max_new_lines = 0; + + for token in SimpleTokenizer::new(contents, TextRange::up_to(contents.text_len())) { + match token.kind() { + SimpleTokenKind::Newline => { + newlines += 1; + } + + SimpleTokenKind::Whitespace => {} + + SimpleTokenKind::Comment => { + max_new_lines = newlines.max(max_new_lines); + newlines = 0; + } + + _ => { + max_new_lines = newlines.max(max_new_lines); + break; + } } } - max_empty_lines + max_new_lines.saturating_sub(1) } #[cfg(test)] @@ -1391,9 +1792,7 @@ mod tests { ); assert_eq!( - max_empty_lines( - "# trailing comment\n\n# own line comment\n\n\n# an other own line comment\n# block" - ), + max_empty_lines("# trailing comment\n\n# own line comment\n\n\n# an other own line comment\n# block"), 2 ); diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__dangling_comment.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__dangling_comment.snap index 58138c9524445..f1b3403f32e20 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__dangling_comment.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__dangling_comment.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..39, source: `(⏎`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_slash_on_same_line.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_slash_on_same_line.snap index 6764fffaaaba8..ca9f11a24cdb9 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_slash_on_same_line.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_slash_on_same_line.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..96, source: `(a=10,/, # trailing positio...t comment.⏎`, }: { @@ -19,7 +19,7 @@ expression: comments.debug(test_case.source_code) "trailing": [], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 90..94, source: `b=20`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_with_defaults.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_with_defaults.snap index 6fa4a9c9d0370..a7f9ec4064686 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_with_defaults.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__non_positional_arguments_with_defaults.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..179, source: `(⏎`, }: { @@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code) "trailing": [], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 15..19, source: `a=10`, }: { @@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code) ], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 173..177, source: `b=20`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__parenthesized_expression.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__parenthesized_expression.snap index e9dbfbf2214d2..0c49034c20c21 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__parenthesized_expression.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__parenthesized_expression.snap @@ -4,19 +4,19 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: ExprName, - range: 1..2, - source: `a`, + kind: ExprBinOp, + range: 30..57, + source: `10 + # More comments⏎`, }: { - "leading": [], - "dangling": [], - "trailing": [ + "leading": [ SourceComment { text: "# Trailing comment", position: EndOfLine, formatted: false, }, ], + "dangling": [], + "trailing": [], }, Node { kind: ExprConstant, diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment.snap index aa1f34eb1f153..a8a9305375d39 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..170, source: `(⏎`, }: { @@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code) "trailing": [], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 15..16, source: `a`, }: { @@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code) ], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 166..167, source: `b`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment_without_following_node.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment_without_following_node.snap index 2c93c46b007b7..9e9db25a5ec0b 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment_without_following_node.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_comment_without_following_node.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..166, source: `(⏎`, }: { @@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code) "trailing": [], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 15..16, source: `a`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_leading_comma_comment.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_leading_comma_comment.snap index aa1f34eb1f153..a8a9305375d39 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_leading_comma_comment.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__positional_argument_only_leading_comma_comment.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: Arguments, + kind: Parameters, range: 9..170, source: `(⏎`, }: { @@ -24,7 +24,7 @@ expression: comments.debug(test_case.source_code) "trailing": [], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 15..16, source: `a`, }: { @@ -39,7 +39,7 @@ expression: comments.debug(test_case.source_code) ], }, Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 166..167, source: `b`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_after_comma.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_after_comma.snap index 5a2c922207932..88f2be2c3094f 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_after_comma.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_after_comma.snap @@ -4,7 +4,7 @@ expression: comments.debug(test_case.source_code) --- { Node { - kind: ArgWithDefault, + kind: ParameterWithDefault, range: 15..16, source: `a`, }: { diff --git a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_function_comment.snap b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_function_comment.snap index 005e4fcf8d40f..9dd6d289d4f1e 100644 --- a/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_function_comment.snap +++ b/crates/ruff_python_formatter/src/comments/snapshots/ruff_python_formatter__comments__tests__trailing_function_comment.snap @@ -34,15 +34,15 @@ expression: comments.debug(test_case.source_code) ], }, Node { - kind: StmtFunctionDef, - range: 193..237, - source: `def other(y, z):⏎`, + kind: StmtIf, + range: 214..237, + source: `if y == z:⏎`, }: { "leading": [], "dangling": [], "trailing": [ SourceComment { - text: "# Trailing `other` function comment", + text: "# Trailing `if` statement comment", position: OwnLine, formatted: false, }, @@ -57,7 +57,22 @@ expression: comments.debug(test_case.source_code) "dangling": [], "trailing": [ SourceComment { - text: "# Trailing `if` comment", + text: "# Trailing `pass` comment", + position: OwnLine, + formatted: false, + }, + ], + }, + Node { + kind: StmtFunctionDef, + range: 333..357, + source: `def func():⏎`, + }: { + "leading": [], + "dangling": [], + "trailing": [ + SourceComment { + text: "# Trailing `func` function comment", position: OwnLine, formatted: false, }, diff --git a/crates/ruff_python_formatter/src/comments/visitor.rs b/crates/ruff_python_formatter/src/comments/visitor.rs index a2be90c22d5b4..f779820a35a40 100644 --- a/crates/ruff_python_formatter/src/comments/visitor.rs +++ b/crates/ruff_python_formatter/src/comments/visitor.rs @@ -1,9 +1,6 @@ use std::iter::Peekable; -use ruff_python_ast::{ - Alias, Arg, ArgWithDefault, Arguments, Comprehension, Decorator, ElifElseClause, ExceptHandler, - Expr, Keyword, MatchCase, Mod, Pattern, Ranged, Stmt, TypeParam, WithItem, -}; +use ruff_python_ast::{Mod, Ranged, Stmt}; use ruff_text_size::{TextRange, TextSize}; use ruff_formatter::{SourceCode, SourceCodeSlice}; @@ -47,14 +44,22 @@ impl<'a> CommentsVisitor<'a> { self.finish() } - fn start_node(&mut self, node: N) -> TraversalSignal - where - N: Into>, - { - self.start_node_impl(node.into()) + // Try to skip the subtree if + // * there are no comments + // * if the next comment comes after this node (meaning, this nodes subtree contains no comments) + fn can_skip(&mut self, node_end: TextSize) -> bool { + self.comment_ranges + .peek() + .map_or(true, |next_comment| next_comment.start() >= node_end) + } + + fn finish(self) -> CommentsMap<'a> { + self.builder.finish() } +} - fn start_node_impl(&mut self, node: AnyNodeRef<'a>) -> TraversalSignal { +impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> { + fn enter_node(&mut self, node: AnyNodeRef<'ast>) -> TraversalSignal { let node_range = node.range(); let enclosing_node = self.parents.last().copied().unwrap_or(node); @@ -95,23 +100,7 @@ impl<'a> CommentsVisitor<'a> { } } - // Try to skip the subtree if - // * there are no comments - // * if the next comment comes after this node (meaning, this nodes subtree contains no comments) - fn can_skip(&mut self, node_end: TextSize) -> bool { - self.comment_ranges - .peek() - .map_or(true, |next_comment| next_comment.start() >= node_end) - } - - fn finish_node(&mut self, node: N) - where - N: Into>, - { - self.finish_node_impl(node.into()); - } - - fn finish_node_impl(&mut self, node: AnyNodeRef<'a>) { + fn leave_node(&mut self, node: AnyNodeRef<'ast>) { // We are leaving this node, pop it from the parent stack. self.parents.pop(); @@ -129,8 +118,8 @@ impl<'a> CommentsVisitor<'a> { let comment = DecoratedComment { enclosing: node, - preceding: self.preceding_node, parent: self.parents.last().copied(), + preceding: self.preceding_node, following: None, line_position: text_position(*comment_range, self.source_code), slice: self.source_code.slice(*comment_range), @@ -147,19 +136,6 @@ impl<'a> CommentsVisitor<'a> { self.preceding_node = Some(node); } - fn finish(self) -> CommentsMap<'a> { - self.builder.finish() - } -} - -impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> { - fn visit_mod(&mut self, module: &'ast Mod) { - if self.start_node(module).is_traverse() { - walk_module(self, module); - } - self.finish_node(module); - } - fn visit_body(&mut self, body: &'ast [Stmt]) { match body { [] => { @@ -179,126 +155,6 @@ impl<'ast> PreorderVisitor<'ast> for CommentsVisitor<'ast> { } } } - - fn visit_stmt(&mut self, stmt: &'ast Stmt) { - if self.start_node(stmt).is_traverse() { - walk_stmt(self, stmt); - } - self.finish_node(stmt); - } - - fn visit_annotation(&mut self, expr: &'ast Expr) { - if self.start_node(expr).is_traverse() { - walk_expr(self, expr); - } - self.finish_node(expr); - } - - fn visit_decorator(&mut self, decorator: &'ast Decorator) { - if self.start_node(decorator).is_traverse() { - walk_decorator(self, decorator); - } - self.finish_node(decorator); - } - - fn visit_expr(&mut self, expr: &'ast Expr) { - if self.start_node(expr).is_traverse() { - walk_expr(self, expr); - } - self.finish_node(expr); - } - - fn visit_comprehension(&mut self, comprehension: &'ast Comprehension) { - if self.start_node(comprehension).is_traverse() { - walk_comprehension(self, comprehension); - } - self.finish_node(comprehension); - } - - fn visit_except_handler(&mut self, except_handler: &'ast ExceptHandler) { - if self.start_node(except_handler).is_traverse() { - walk_except_handler(self, except_handler); - } - self.finish_node(except_handler); - } - - fn visit_format_spec(&mut self, format_spec: &'ast Expr) { - if self.start_node(format_spec).is_traverse() { - walk_expr(self, format_spec); - } - self.finish_node(format_spec); - } - - fn visit_arguments(&mut self, arguments: &'ast Arguments) { - if self.start_node(arguments).is_traverse() { - walk_arguments(self, arguments); - } - self.finish_node(arguments); - } - - fn visit_arg(&mut self, arg: &'ast Arg) { - if self.start_node(arg).is_traverse() { - walk_arg(self, arg); - } - self.finish_node(arg); - } - - fn visit_arg_with_default(&mut self, arg_with_default: &'ast ArgWithDefault) { - if self.start_node(arg_with_default).is_traverse() { - walk_arg_with_default(self, arg_with_default); - } - self.finish_node(arg_with_default); - } - - fn visit_keyword(&mut self, keyword: &'ast Keyword) { - if self.start_node(keyword).is_traverse() { - walk_keyword(self, keyword); - } - self.finish_node(keyword); - } - - fn visit_alias(&mut self, alias: &'ast Alias) { - if self.start_node(alias).is_traverse() { - walk_alias(self, alias); - } - self.finish_node(alias); - } - - fn visit_with_item(&mut self, with_item: &'ast WithItem) { - if self.start_node(with_item).is_traverse() { - walk_with_item(self, with_item); - } - - self.finish_node(with_item); - } - - fn visit_match_case(&mut self, match_case: &'ast MatchCase) { - if self.start_node(match_case).is_traverse() { - walk_match_case(self, match_case); - } - self.finish_node(match_case); - } - - fn visit_pattern(&mut self, pattern: &'ast Pattern) { - if self.start_node(pattern).is_traverse() { - walk_pattern(self, pattern); - } - self.finish_node(pattern); - } - - fn visit_elif_else_clause(&mut self, elif_else_clause: &'ast ElifElseClause) { - if self.start_node(elif_else_clause).is_traverse() { - walk_elif_else_clause(self, elif_else_clause); - } - self.finish_node(elif_else_clause); - } - - fn visit_type_param(&mut self, type_param: &'ast TypeParam) { - if self.start_node(type_param).is_traverse() { - walk_type_param(self, type_param); - } - self.finish_node(type_param); - } } fn text_position(comment_range: TextRange, source_code: SourceCode) -> CommentLinePosition { @@ -643,17 +499,16 @@ impl<'a> CommentPlacement<'a> { comment: comment.into(), } } -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum TraversalSignal { - Traverse, - Skip, -} -impl TraversalSignal { - const fn is_traverse(self) -> bool { - matches!(self, TraversalSignal::Traverse) + /// Chains the placement with the given function. + /// + /// Returns `self` when the placement is non-[`CommentPlacement::Default`]. Otherwise, calls the + /// function with the comment and returns the result. + pub(super) fn or_else) -> Self>(self, f: F) -> Self { + match self { + Self::Default(comment) => f(comment), + _ => self, + } } } diff --git a/crates/ruff_python_formatter/src/context.rs b/crates/ruff_python_formatter/src/context.rs index 23a3530a242f9..01caed9e6854d 100644 --- a/crates/ruff_python_formatter/src/context.rs +++ b/crates/ruff_python_formatter/src/context.rs @@ -1,9 +1,9 @@ use crate::comments::Comments; use crate::PyFormatOptions; -use ruff_formatter::prelude::*; -use ruff_formatter::{Arguments, Buffer, FormatContext, GroupId, SourceCode}; +use ruff_formatter::{Buffer, FormatContext, GroupId, SourceCode}; use ruff_source_file::Locator; use std::fmt::{Debug, Formatter}; +use std::ops::{Deref, DerefMut}; #[derive(Clone)] pub struct PyFormatContext<'a> { @@ -96,6 +96,7 @@ impl NodeLevel { } } +/// Change the [`NodeLevel`] of the formatter for the lifetime of this struct pub(crate) struct WithNodeLevel<'ast, 'buf, B> where B: Buffer>, @@ -119,16 +120,25 @@ where saved_level, } } +} + +impl<'ast, 'buf, B> Deref for WithNodeLevel<'ast, 'buf, B> +where + B: Buffer>, +{ + type Target = B; - #[inline] - pub(crate) fn write_fmt(&mut self, arguments: Arguments) -> FormatResult<()> { - self.buffer.write_fmt(arguments) + fn deref(&self) -> &Self::Target { + self.buffer } +} - #[allow(unused)] - #[inline] - pub(crate) fn write_element(&mut self, element: FormatElement) -> FormatResult<()> { - self.buffer.write_element(element) +impl<'ast, 'buf, B> DerefMut for WithNodeLevel<'ast, 'buf, B> +where + B: Buffer>, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + self.buffer } } diff --git a/crates/ruff_python_formatter/src/expression/expr_attribute.rs b/crates/ruff_python_formatter/src/expression/expr_attribute.rs index a577ae88d0610..c00fbd261424d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_attribute.rs +++ b/crates/ruff_python_formatter/src/expression/expr_attribute.rs @@ -1,15 +1,30 @@ -use ruff_python_ast::{Constant, Expr, ExprAttribute, ExprConstant}; - -use ruff_formatter::write; +use ruff_formatter::{write, FormatRuleWithOptions}; use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{Constant, Expr, ExprAttribute, ExprConstant, Ranged}; +use ruff_python_trivia::{find_only_token_in_range, SimpleTokenKind}; +use ruff_text_size::TextRange; -use crate::comments::{leading_comments, trailing_comments}; -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses}; +use crate::comments::{dangling_comments, SourceComment}; +use crate::expression::parentheses::{ + is_expression_parenthesized, NeedsParentheses, OptionalParentheses, Parentheses, +}; +use crate::expression::CallChainLayout; use crate::prelude::*; use crate::FormatNodeRule; #[derive(Default)] -pub struct FormatExprAttribute; +pub struct FormatExprAttribute { + call_chain_layout: CallChainLayout, +} + +impl FormatRuleWithOptions> for FormatExprAttribute { + type Options = CallChainLayout; + + fn with_options(mut self, options: Self::Options) -> Self { + self.call_chain_layout = options; + self + } +} impl FormatNodeRule for FormatExprAttribute { fn fmt_fields(&self, item: &ExprAttribute, f: &mut PyFormatter) -> FormatResult<()> { @@ -20,51 +35,104 @@ impl FormatNodeRule for FormatExprAttribute { ctx: _, } = item; - let needs_parentheses = matches!( - value.as_ref(), - Expr::Constant(ExprConstant { - value: Constant::Int(_) | Constant::Float(_), - .. - }) - ); + let call_chain_layout = self.call_chain_layout.apply_in_node(item, f); - let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(item); - let leading_attribute_comments_start = - dangling_comments.partition_point(|comment| comment.line_position().is_end_of_line()); - let (trailing_dot_comments, leading_attribute_comments) = - dangling_comments.split_at(leading_attribute_comments_start); + let format_inner = format_with(|f: &mut PyFormatter| { + let needs_parentheses = matches!( + value.as_ref(), + Expr::Constant(ExprConstant { + value: Constant::Int(_) | Constant::Float(_), + .. + }) + ); - if needs_parentheses { - value.format().with_options(Parentheses::Always).fmt(f)?; - } else if let Expr::Attribute(expr_attribute) = value.as_ref() { - // We're in a attribute chain (`a.b.c`). The outermost node adds parentheses if - // required, the inner ones don't need them so we skip the `Expr` formatting that - // normally adds the parentheses. - expr_attribute.format().fmt(f)?; - } else { - value.format().fmt(f)?; - } + if needs_parentheses { + value.format().with_options(Parentheses::Always).fmt(f)?; + } else if call_chain_layout == CallChainLayout::Fluent { + match value.as_ref() { + Expr::Attribute(expr) => { + expr.format().with_options(call_chain_layout).fmt(f)?; + } + Expr::Call(expr) => { + expr.format().with_options(call_chain_layout).fmt(f)?; + if call_chain_layout == CallChainLayout::Fluent { + // Format the dot on its own line + soft_line_break().fmt(f)?; + } + } + Expr::Subscript(expr) => { + expr.format().with_options(call_chain_layout).fmt(f)?; + if call_chain_layout == CallChainLayout::Fluent { + // Format the dot on its own line + soft_line_break().fmt(f)?; + } + } + _ => { + // This matches [`CallChainLayout::from_expression`] + if is_expression_parenthesized(value.as_ref().into(), f.context().source()) + { + value.format().with_options(Parentheses::Always).fmt(f)?; + // Format the dot on its own line + soft_line_break().fmt(f)?; + } else { + value.format().fmt(f)?; + } + } + } + } else { + value.format().fmt(f)?; + } - if comments.has_trailing_own_line_comments(value.as_ref()) { - hard_line_break().fmt(f)?; - } + // Identify dangling comments before and after the dot: + // ```python + // ( + // ( + // a + // ) # `before_dot` + // # `before_dot` + // . # `after_dot` + // # `after_dot` + // b + // ) + // ``` + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + let (before_dot, after_dot) = if dangling.is_empty() { + (dangling, dangling) + } else { + let dot_token = find_only_token_in_range( + TextRange::new(item.value.end(), item.attr.start()), + SimpleTokenKind::Dot, + f.context().source(), + ); + dangling.split_at( + dangling.partition_point(|comment| comment.start() < dot_token.start()), + ) + }; - write!( - f, - [ - text("."), - trailing_comments(trailing_dot_comments), - (!leading_attribute_comments.is_empty()).then_some(hard_line_break()), - leading_comments(leading_attribute_comments), - attr.format() - ] - ) + write!( + f, + [ + dangling_comments(before_dot), + text("."), + dangling_comments(after_dot), + attr.format() + ] + ) + }); + + let is_call_chain_root = self.call_chain_layout == CallChainLayout::Default + && call_chain_layout == CallChainLayout::Fluent; + if is_call_chain_root { + write!(f, [group(&format_inner)]) + } else { + write!(f, [format_inner]) + } } fn fmt_dangling_comments( &self, - _node: &ExprAttribute, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { // handle in `fmt_fields` @@ -79,14 +147,14 @@ impl NeedsParentheses for ExprAttribute { context: &PyFormatContext, ) -> OptionalParentheses { // Checks if there are any own line comments in an attribute chain (a.b.c). - if context - .comments() - .dangling_comments(self) - .iter() - .any(|comment| comment.line_position().is_own_line()) - || context.comments().has_trailing_own_line_comments(self) + if CallChainLayout::from_expression(self.into(), context.source()) + == CallChainLayout::Fluent { + OptionalParentheses::Multiline + } else if context.comments().has_dangling(self) { OptionalParentheses::Always + } else if self.value.is_name_expr() { + OptionalParentheses::BestFit } else { self.value.needs_parentheses(self.into(), context) } diff --git a/crates/ruff_python_formatter/src/expression/expr_await.rs b/crates/ruff_python_formatter/src/expression/expr_await.rs index 496b2ff763aec..b499e901730cc 100644 --- a/crates/ruff_python_formatter/src/expression/expr_await.rs +++ b/crates/ruff_python_formatter/src/expression/expr_await.rs @@ -20,7 +20,7 @@ impl FormatNodeRule for FormatExprAwait { [ text("await"), space(), - maybe_parenthesize_expression(value, item, Parenthesize::IfRequired) + maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) ] ) } diff --git a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs index af24f6ea4afba..fd8dd96a9e583 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs @@ -1,17 +1,15 @@ use std::iter; -use ruff_python_ast::{ - Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, UnaryOp, -}; use smallvec::SmallVec; -use ruff_formatter::{ - format_args, write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions, +use ruff_formatter::{format_args, write, FormatOwnedWithRule, FormatRefWithRule}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{ + Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, StringConstant, + UnaryOp, }; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; -use ruff_python_ast::str::is_implicit_concatenation; -use crate::comments::{trailing_comments, trailing_node_comments}; +use crate::comments::{trailing_comments, trailing_node_comments, SourceComment}; use crate::expression::expr_constant::ExprConstantLayout; use crate::expression::parentheses::{ in_parentheses_only_group, in_parentheses_only_soft_line_break, @@ -19,23 +17,11 @@ use crate::expression::parentheses::{ NeedsParentheses, OptionalParentheses, }; use crate::expression::string::StringLayout; -use crate::expression::Parentheses; use crate::prelude::*; use crate::FormatNodeRule; #[derive(Default)] -pub struct FormatExprBinOp { - parentheses: Option, -} - -impl FormatRuleWithOptions> for FormatExprBinOp { - type Options = Option; - - fn with_options(mut self, options: Self::Options) -> Self { - self.parentheses = options; - self - } -} +pub struct FormatExprBinOp; impl FormatNodeRule for FormatExprBinOp { fn fmt_fields(&self, item: &ExprBinOp, f: &mut PyFormatter) -> FormatResult<()> { @@ -43,10 +29,7 @@ impl FormatNodeRule for FormatExprBinOp { match Self::layout(item, f.context()) { BinOpLayout::LeftString(expression) => { - let right_has_leading_comment = f - .context() - .comments() - .has_leading_comments(item.right.as_ref()); + let right_has_leading_comment = comments.has_leading(item.right.as_ref()); let format_right_and_op = format_with(|f| { if right_has_leading_comment { @@ -87,10 +70,7 @@ impl FormatNodeRule for FormatExprBinOp { let binary_chain: SmallVec<[&ExprBinOp; 4]> = iter::successors(Some(item), |parent| { parent.left.as_bin_op_expr().and_then(|bin_expression| { - if is_expression_parenthesized( - bin_expression.as_any_node_ref(), - source, - ) { + if is_expression_parenthesized(bin_expression.into(), source) { None } else { Some(bin_expression) @@ -115,7 +95,7 @@ impl FormatNodeRule for FormatExprBinOp { right, } = current; - let operator_comments = comments.dangling_comments(current); + let operator_comments = comments.dangling(current); let needs_space = !is_simple_power_expression(current); let before_operator_space = if needs_space { @@ -134,9 +114,7 @@ impl FormatNodeRule for FormatExprBinOp { )?; // Format the operator on its own line if the right side has any leading comments. - if comments.has_leading_comments(right.as_ref()) - || !operator_comments.is_empty() - { + if comments.has_leading(right.as_ref()) || !operator_comments.is_empty() { hard_line_break().fmt(f)?; } else if needs_space { space().fmt(f)?; @@ -161,7 +139,11 @@ impl FormatNodeRule for FormatExprBinOp { } } - fn fmt_dangling_comments(&self, _node: &ExprBinOp, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled inside of `fmt_fields` Ok(()) } @@ -171,8 +153,11 @@ impl FormatExprBinOp { fn layout<'a>(bin_op: &'a ExprBinOp, context: &PyFormatContext) -> BinOpLayout<'a> { if let Some( constant @ ExprConstant { - value: Constant::Str(_), - range, + value: + Constant::Str(StringConstant { + implicit_concatenated: true, + .. + }), .. }, ) = bin_op.left.as_constant_expr() @@ -181,9 +166,8 @@ impl FormatExprBinOp { if bin_op.op == Operator::Mod && context.node_level().is_parenthesized() - && !comments.has_dangling_comments(constant) - && !comments.has_dangling_comments(bin_op) - && is_implicit_concatenation(&context.source()[*range]) + && !comments.has_dangling(constant) + && !comments.has_dangling(bin_op) { BinOpLayout::LeftString(constant) } else { @@ -255,7 +239,7 @@ impl<'ast> IntoFormat> for Operator { } impl FormatRule> for FormatOperator { - fn fmt(&self, item: &Operator, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, item: &Operator, f: &mut PyFormatter) -> FormatResult<()> { let operator = match item { Operator::Add => "+", Operator::Sub => "-", diff --git a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs index 2a92f2f0cbfef..8b2f9feeda655 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs @@ -1,22 +1,32 @@ +use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{BoolOp, Expr, ExprBoolOp}; + use crate::comments::leading_comments; use crate::expression::parentheses::{ in_parentheses_only_group, in_parentheses_only_soft_line_break_or_space, NeedsParentheses, - OptionalParentheses, Parentheses, + OptionalParentheses, }; use crate::prelude::*; -use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::{BoolOp, ExprBoolOp}; + +use super::parentheses::is_expression_parenthesized; #[derive(Default)] pub struct FormatExprBoolOp { - parentheses: Option, + layout: BoolOpLayout, +} + +#[derive(Default, Copy, Clone)] +pub enum BoolOpLayout { + #[default] + Default, + Chained, } impl FormatRuleWithOptions> for FormatExprBoolOp { - type Options = Option; + type Options = BoolOpLayout; fn with_options(mut self, options: Self::Options) -> Self { - self.parentheses = options; + self.layout = options; self } } @@ -37,10 +47,10 @@ impl FormatNodeRule for FormatExprBoolOp { return Ok(()); }; - write!(f, [in_parentheses_only_group(&first.format())])?; + FormatValue { value: first }.fmt(f)?; for value in values { - let leading_value_comments = comments.leading_comments(value); + let leading_value_comments = comments.leading(value); // Format the expressions leading comments **before** the operator if leading_value_comments.is_empty() { write!(f, [in_parentheses_only_soft_line_break_or_space()])?; @@ -51,20 +61,20 @@ impl FormatNodeRule for FormatExprBoolOp { )?; } - write!( - f, - [ - op.format(), - space(), - in_parentheses_only_group(&value.format()) - ] - )?; + write!(f, [op.format(), space()])?; + + FormatValue { value }.fmt(f)?; } Ok(()) }); - in_parentheses_only_group(&inner).fmt(f) + if matches!(self.layout, BoolOpLayout::Chained) { + // Chained boolean operations should not be given a new group + inner.fmt(f) + } else { + in_parentheses_only_group(&inner).fmt(f) + } } } @@ -78,6 +88,24 @@ impl NeedsParentheses for ExprBoolOp { } } +struct FormatValue<'a> { + value: &'a Expr, +} + +impl Format> for FormatValue<'_> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + match self.value { + Expr::BoolOp(bool_op) + if !is_expression_parenthesized(bool_op.into(), f.context().source()) => + { + // Mark chained boolean operations e.g. `x and y or z` and avoid creating a new group + write!(f, [bool_op.format().with_options(BoolOpLayout::Chained)]) + } + _ => write!(f, [in_parentheses_only_group(&self.value.format())]), + } + } +} + #[derive(Copy, Clone)] pub struct FormatBoolOp; @@ -98,7 +126,7 @@ impl<'ast> IntoFormat> for BoolOp { } impl FormatRule> for FormatBoolOp { - fn fmt(&self, item: &BoolOp, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, item: &BoolOp, f: &mut PyFormatter) -> FormatResult<()> { let operator = match item { BoolOp::And => "and", BoolOp::Or => "or", diff --git a/crates/ruff_python_formatter/src/expression/expr_call.rs b/crates/ruff_python_formatter/src/expression/expr_call.rs index 85ecfff06bc0f..613fa3f091af9 100644 --- a/crates/ruff_python_formatter/src/expression/expr_call.rs +++ b/crates/ruff_python_formatter/src/expression/expr_call.rs @@ -1,117 +1,76 @@ -use ruff_python_ast::{Expr, ExprCall, Ranged}; -use ruff_text_size::{TextRange, TextSize}; - -use crate::builders::empty_parenthesized_with_dangling_comments; -use ruff_formatter::write; +use ruff_formatter::FormatRuleWithOptions; use ruff_python_ast::node::AnyNodeRef; -use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_python_ast::{Expr, ExprCall}; -use crate::expression::expr_generator_exp::GeneratorExpParentheses; -use crate::expression::parentheses::{ - parenthesized, NeedsParentheses, OptionalParentheses, Parentheses, -}; +use crate::comments::{dangling_comments, SourceComment}; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::expression::CallChainLayout; use crate::prelude::*; use crate::FormatNodeRule; #[derive(Default)] -pub struct FormatExprCall; +pub struct FormatExprCall { + call_chain_layout: CallChainLayout, +} + +impl FormatRuleWithOptions> for FormatExprCall { + type Options = CallChainLayout; + + fn with_options(mut self, options: Self::Options) -> Self { + self.call_chain_layout = options; + self + } +} impl FormatNodeRule for FormatExprCall { fn fmt_fields(&self, item: &ExprCall, f: &mut PyFormatter) -> FormatResult<()> { let ExprCall { range: _, func, - args, - keywords, + arguments, } = item; - // We have a case with `f()` without any argument, which is a special case because we can - // have a comment with no node attachment inside: - // ```python - // f( - // # This function has a dangling comment - // ) - // ``` - if args.is_empty() && keywords.is_empty() { - let comments = f.context().comments().clone(); - return write!( - f, - [ - func.format(), - empty_parenthesized_with_dangling_comments( - text("("), - comments.dangling_comments(item), - text(")"), - ) - ] - ); - } + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + let call_chain_layout = self.call_chain_layout.apply_in_node(item, f); - let all_args = format_with(|f: &mut PyFormatter| { - let source = f.context().source(); - let mut joiner = f.join_comma_separated(item.end()); - match args.as_slice() { - [argument] if keywords.is_empty() => { - match argument { - Expr::GeneratorExp(generator_exp) => joiner.entry( - generator_exp, - &generator_exp - .format() - .with_options(GeneratorExpParentheses::StripIfOnlyFunctionArg), - ), - other => { - let parentheses = - if is_single_argument_parenthesized(argument, item.end(), source) { - Parentheses::Always - } else { - Parentheses::Never - }; - joiner.entry(other, &other.format().with_options(parentheses)) - } - }; - } - arguments => { - joiner - .entries( - // We have the parentheses from the call so the arguments never need any - arguments - .iter() - .map(|arg| (arg, arg.format().with_options(Parentheses::Preserve))), - ) - .nodes(keywords.iter()); - } - } + let fmt_func = format_with(|f| { + // Format the function expression. + match func.as_ref() { + Expr::Attribute(expr) => expr.format().with_options(call_chain_layout).fmt(f), + Expr::Call(expr) => expr.format().with_options(call_chain_layout).fmt(f), + Expr::Subscript(expr) => expr.format().with_options(call_chain_layout).fmt(f), + _ => func.format().fmt(f), + }?; - joiner.finish() + // Format comments between the function and its arguments. + dangling_comments(dangling).fmt(f)?; + + // Format the arguments. + arguments.format().fmt(f) }); - write!( - f, - [ - func.format(), - // The outer group is for things like - // ```python - // get_collection( - // hey_this_is_a_very_long_call, - // it_has_funny_attributes_asdf_asdf, - // too_long_for_the_line, - // really=True, - // ) - // ``` - // The inner group is for things like: - // ```python - // get_collection( - // hey_this_is_a_very_long_call, it_has_funny_attributes_asdf_asdf, really=True - // ) - // ``` - // TODO(konstin): Doesn't work see wrongly formatted test - parenthesized("(", &group(&all_args), ")") - ] - ) + // Allow to indent the parentheses while + // ```python + // g1 = ( + // queryset.distinct().order_by(field.name).values_list(field_name_flat_long_long=True) + // ) + // ``` + if call_chain_layout == CallChainLayout::Fluent + && self.call_chain_layout == CallChainLayout::Default + { + group(&fmt_func).fmt(f) + } else { + fmt_func.fmt(f) + } } - fn fmt_dangling_comments(&self, _node: &ExprCall, _f: &mut PyFormatter) -> FormatResult<()> { - // Handled in `fmt_fields` + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { Ok(()) } } @@ -122,31 +81,14 @@ impl NeedsParentheses for ExprCall { _parent: AnyNodeRef, context: &PyFormatContext, ) -> OptionalParentheses { - self.func.needs_parentheses(self.into(), context) - } -} - -fn is_single_argument_parenthesized(argument: &Expr, call_end: TextSize, source: &str) -> bool { - let mut has_seen_r_paren = false; - - for token in - SimpleTokenizer::new(source, TextRange::new(argument.end(), call_end)).skip_trivia() - { - match token.kind() { - SimpleTokenKind::RParen => { - if has_seen_r_paren { - return true; - } - has_seen_r_paren = true; - } - // Skip over any trailing comma - SimpleTokenKind::Comma => continue, - _ => { - // Passed the arguments - break; - } + if CallChainLayout::from_expression(self.into(), context.source()) + == CallChainLayout::Fluent + { + OptionalParentheses::Multiline + } else if context.comments().has_dangling(self) { + OptionalParentheses::Always + } else { + self.func.needs_parentheses(self.into(), context) } } - - false } diff --git a/crates/ruff_python_formatter/src/expression/expr_compare.rs b/crates/ruff_python_formatter/src/expression/expr_compare.rs index a2b1b176fc08c..a217d45db6003 100644 --- a/crates/ruff_python_formatter/src/expression/expr_compare.rs +++ b/crates/ruff_python_formatter/src/expression/expr_compare.rs @@ -1,27 +1,16 @@ -use crate::comments::leading_comments; +use crate::comments::{leading_comments, SourceComment}; use crate::expression::parentheses::{ in_parentheses_only_group, in_parentheses_only_soft_line_break_or_space, NeedsParentheses, - OptionalParentheses, Parentheses, + OptionalParentheses, }; use crate::prelude::*; use crate::FormatNodeRule; -use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; +use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::{CmpOp, ExprCompare}; #[derive(Default)] -pub struct FormatExprCompare { - parentheses: Option, -} - -impl FormatRuleWithOptions> for FormatExprCompare { - type Options = Option; - - fn with_options(mut self, options: Self::Options) -> Self { - self.parentheses = options; - self - } -} +pub struct FormatExprCompare; impl FormatNodeRule for FormatExprCompare { fn fmt_fields(&self, item: &ExprCompare, f: &mut PyFormatter) -> FormatResult<()> { @@ -40,7 +29,7 @@ impl FormatNodeRule for FormatExprCompare { assert_eq!(comparators.len(), ops.len()); for (operator, comparator) in ops.iter().zip(comparators) { - let leading_comparator_comments = comments.leading_comments(comparator); + let leading_comparator_comments = comments.leading(comparator); if leading_comparator_comments.is_empty() { write!(f, [in_parentheses_only_soft_line_break_or_space()])?; } else { @@ -69,6 +58,15 @@ impl FormatNodeRule for FormatExprCompare { in_parentheses_only_group(&inner).fmt(f) } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Node can not have dangling comments + Ok(()) + } } impl NeedsParentheses for ExprCompare { @@ -101,7 +99,7 @@ impl<'ast> IntoFormat> for CmpOp { } impl FormatRule> for FormatCmpOp { - fn fmt(&self, item: &CmpOp, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, item: &CmpOp, f: &mut PyFormatter) -> FormatResult<()> { let operator = match item { CmpOp::Eq => "==", CmpOp::NotEq => "!=", diff --git a/crates/ruff_python_formatter/src/expression/expr_constant.rs b/crates/ruff_python_formatter/src/expression/expr_constant.rs index 8594e2640d928..92e3461b7532d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_constant.rs +++ b/crates/ruff_python_formatter/src/expression/expr_constant.rs @@ -1,12 +1,11 @@ -use ruff_python_ast::{Constant, ExprConstant, Ranged}; -use ruff_text_size::{TextLen, TextRange}; - +use crate::comments::SourceComment; use ruff_formatter::FormatRuleWithOptions; use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::str::is_implicit_concatenation; +use ruff_python_ast::{Constant, ExprConstant, Ranged}; +use ruff_text_size::{TextLen, TextRange}; use crate::expression::number::{FormatComplex, FormatFloat, FormatInt}; -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::expression::parentheses::{should_use_best_fit, NeedsParentheses, OptionalParentheses}; use crate::expression::string::{ AnyString, FormatString, StringLayout, StringPrefix, StringQuotes, }; @@ -67,7 +66,7 @@ impl FormatNodeRule for FormatExprConstant { fn fmt_dangling_comments( &self, - _node: &ExprConstant, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { Ok(()) @@ -80,14 +79,16 @@ impl NeedsParentheses for ExprConstant { _parent: AnyNodeRef, context: &PyFormatContext, ) -> OptionalParentheses { - if self.value.is_str() || self.value.is_bytes() { - let contents = context.locator().slice(self.range()); - // Don't wrap triple quoted strings - if is_multiline_string(self, context.source()) || !is_implicit_concatenation(contents) { - OptionalParentheses::Never - } else { - OptionalParentheses::Multiline - } + if self.value.is_implicit_concatenated() { + OptionalParentheses::Multiline + } else if is_multiline_string(self, context.source()) + || self.value.is_none() + || self.value.is_bool() + || self.value.is_ellipsis() + { + OptionalParentheses::Never + } else if should_use_best_fit(self, context) { + OptionalParentheses::BestFit } else { OptionalParentheses::Never } @@ -101,7 +102,8 @@ pub(super) fn is_multiline_string(constant: &ExprConstant, source: &str) -> bool let quotes = StringQuotes::parse(&contents[TextRange::new(prefix.text_len(), contents.text_len())]); - quotes.map_or(false, StringQuotes::is_triple) && contents.contains(['\n', '\r']) + quotes.is_some_and(StringQuotes::is_triple) + && memchr::memchr2(b'\n', b'\r', contents.as_bytes()).is_some() } else { false } diff --git a/crates/ruff_python_formatter/src/expression/expr_dict.rs b/crates/ruff_python_formatter/src/expression/expr_dict.rs index c86b3ca03dcc1..840f973297abd 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict.rs @@ -1,14 +1,16 @@ -use crate::builders::empty_parenthesized_with_dangling_comments; -use crate::comments::leading_comments; -use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; -use crate::prelude::*; -use crate::FormatNodeRule; use ruff_formatter::{format_args, write}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::Ranged; use ruff_python_ast::{Expr, ExprDict}; use ruff_text_size::TextRange; +use crate::comments::{leading_comments, SourceComment}; +use crate::expression::parentheses::{ + empty_parenthesized, parenthesized, NeedsParentheses, OptionalParentheses, +}; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatExprDict; @@ -28,7 +30,7 @@ impl Ranged for KeyValuePair<'_> { } impl Format> for KeyValuePair<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { if let Some(key) = self.key { write!( f, @@ -41,7 +43,7 @@ impl Format> for KeyValuePair<'_> { ) } else { let comments = f.context().comments().clone(); - let leading_value_comments = comments.leading_comments(self.value); + let leading_value_comments = comments.leading(self.value); write!( f, [ @@ -64,14 +66,11 @@ impl FormatNodeRule for FormatExprDict { debug_assert_eq!(keys.len(), values.len()); + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + if values.is_empty() { - let comments = f.context().comments().clone(); - return empty_parenthesized_with_dangling_comments( - text("{"), - comments.dangling_comments(item), - text("}"), - ) - .fmt(f); + return empty_parenthesized("{", dangling, "}").fmt(f); } let format_pairs = format_with(|f| { @@ -85,10 +84,16 @@ impl FormatNodeRule for FormatExprDict { joiner.finish() }); - parenthesized("{", &format_pairs, "}").fmt(f) + parenthesized("{", &format_pairs, "}") + .with_dangling_comments(dangling) + .fmt(f) } - fn fmt_dangling_comments(&self, _node: &ExprDict, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled by `fmt_fields` Ok(()) } diff --git a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs index 0a17f3bfc14ec..333a4082dc377 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs @@ -1,7 +1,3 @@ -use crate::context::PyFormatContext; -use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; -use crate::AsFormat; -use crate::{FormatNodeRule, FormattedIterExt, PyFormatter}; use ruff_formatter::prelude::{ format_args, format_with, group, soft_line_break_or_space, space, text, }; @@ -9,6 +5,11 @@ use ruff_formatter::{write, Buffer, FormatResult}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::ExprDictComp; +use crate::context::PyFormatContext; +use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; +use crate::AsFormat; +use crate::{FormatNodeRule, FormattedIterExt, PyFormatter}; + #[derive(Default)] pub struct FormatExprDictComp; @@ -27,6 +28,9 @@ impl FormatNodeRule for FormatExprDictComp { .finish() }); + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + write!( f, [parenthesized( @@ -37,10 +41,11 @@ impl FormatNodeRule for FormatExprDictComp { space(), value.format(), soft_line_break_or_space(), - group(&joined) + joined )), "}" - )] + ) + .with_dangling_comments(dangling)] ) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_f_string.rs b/crates/ruff_python_formatter/src/expression/expr_f_string.rs new file mode 100644 index 0000000000000..2d272ce99c1ab --- /dev/null +++ b/crates/ruff_python_formatter/src/expression/expr_f_string.rs @@ -0,0 +1,37 @@ +use super::string::{AnyString, FormatString}; +use crate::context::PyFormatContext; +use memchr::memchr2; + +use crate::expression::parentheses::{should_use_best_fit, NeedsParentheses, OptionalParentheses}; +use crate::prelude::*; +use crate::{FormatNodeRule, PyFormatter}; +use ruff_formatter::FormatResult; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::ExprFString; + +#[derive(Default)] +pub struct FormatExprFString; + +impl FormatNodeRule for FormatExprFString { + fn fmt_fields(&self, item: &ExprFString, f: &mut PyFormatter) -> FormatResult<()> { + FormatString::new(&AnyString::FString(item)).fmt(f) + } +} + +impl NeedsParentheses for ExprFString { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + context: &PyFormatContext, + ) -> OptionalParentheses { + if self.implicit_concatenated { + OptionalParentheses::Multiline + } else if memchr2(b'\n', b'\r', context.source()[self.range].as_bytes()).is_none() + && should_use_best_fit(self, context) + { + OptionalParentheses::BestFit + } else { + OptionalParentheses::Never + } + } +} diff --git a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs index 34b7fb1f65217..12c1a8e0e5e00 100644 --- a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs +++ b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs @@ -1,7 +1,7 @@ use crate::context::PyFormatContext; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use crate::{FormatNodeRule, PyFormatter}; +use ruff_formatter::FormatResult; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::ExprFormattedValue; @@ -9,8 +9,8 @@ use ruff_python_ast::ExprFormattedValue; pub struct FormatExprFormattedValue; impl FormatNodeRule for FormatExprFormattedValue { - fn fmt_fields(&self, item: &ExprFormattedValue, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + fn fmt_fields(&self, _item: &ExprFormattedValue, _f: &mut PyFormatter) -> FormatResult<()> { + unreachable!("Handled inside of `FormatExprFString"); } } diff --git a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs index 3113a494758e0..32fc627f428da 100644 --- a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs @@ -1,22 +1,24 @@ +use ruff_formatter::{format_args, write, Buffer, FormatResult, FormatRuleWithOptions}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::ExprGeneratorExp; + +use crate::comments::SourceComment; use crate::context::PyFormatContext; -use crate::expression::parentheses::parenthesized; -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; use crate::prelude::*; use crate::AsFormat; use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::{format_args, write, Buffer, FormatResult, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::ExprGeneratorExp; #[derive(Eq, PartialEq, Debug, Default)] pub enum GeneratorExpParentheses { #[default] Default, - // skip parens if the generator exp is the only argument to a function, e.g. - // ```python - // all(x for y in z)` - // ``` + /// Skip parens if the generator is the only argument to a function and doesn't contain any + /// dangling comments. For example: + /// ```python + /// all(x for y in z)` + /// ``` StripIfOnlyFunctionArg, } @@ -48,30 +50,41 @@ impl FormatNodeRule for FormatExprGeneratorExp { .finish() }); - if self.parentheses == GeneratorExpParentheses::StripIfOnlyFunctionArg { + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + if self.parentheses == GeneratorExpParentheses::StripIfOnlyFunctionArg + && dangling.is_empty() + { write!( f, - [ - group(&elt.format()), - soft_line_break_or_space(), - group(&joined), - ] + [group(&elt.format()), soft_line_break_or_space(), &joined] ) } else { write!( f, [parenthesized( "(", - &format_args!( + &group(&format_args!( group(&elt.format()), soft_line_break_or_space(), - group(&joined) - ), + joined + )), ")" - )] + ) + .with_dangling_comments(dangling)] ) } } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) + } } impl NeedsParentheses for ExprGeneratorExp { diff --git a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs index 959413664a0d9..00c78c9b9c7e9 100644 --- a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs @@ -30,12 +30,12 @@ impl FormatNodeRule for FormatExprIfExp { [in_parentheses_only_group(&format_args![ body.format(), in_parentheses_only_soft_line_break_or_space(), - leading_comments(comments.leading_comments(test.as_ref())), + leading_comments(comments.leading(test.as_ref())), text("if"), space(), test.format(), in_parentheses_only_soft_line_break_or_space(), - leading_comments(comments.leading_comments(orelse.as_ref())), + leading_comments(comments.leading(orelse.as_ref())), text("else"), space(), orelse.format() diff --git a/crates/ruff_python_formatter/src/expression/expr_ipy_escape_command.rs b/crates/ruff_python_formatter/src/expression/expr_ipy_escape_command.rs new file mode 100644 index 0000000000000..00afaee7568e2 --- /dev/null +++ b/crates/ruff_python_formatter/src/expression/expr_ipy_escape_command.rs @@ -0,0 +1,11 @@ +use crate::prelude::*; +use ruff_python_ast::{ExprIpyEscapeCommand, Ranged}; + +#[derive(Default)] +pub struct FormatExprIpyEscapeCommand; + +impl FormatNodeRule for FormatExprIpyEscapeCommand { + fn fmt_fields(&self, item: &ExprIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> { + source_text_slice(item.range(), ContainsNewlines::No).fmt(f) + } +} diff --git a/crates/ruff_python_formatter/src/expression/expr_joined_str.rs b/crates/ruff_python_formatter/src/expression/expr_joined_str.rs deleted file mode 100644 index e857ea0b30ebf..0000000000000 --- a/crates/ruff_python_formatter/src/expression/expr_joined_str.rs +++ /dev/null @@ -1,27 +0,0 @@ -use super::string::{AnyString, FormatString}; -use crate::context::PyFormatContext; -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; -use crate::prelude::*; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::FormatResult; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::ExprJoinedStr; - -#[derive(Default)] -pub struct FormatExprJoinedStr; - -impl FormatNodeRule for FormatExprJoinedStr { - fn fmt_fields(&self, item: &ExprJoinedStr, f: &mut PyFormatter) -> FormatResult<()> { - FormatString::new(&AnyString::JoinedStr(item)).fmt(f) - } -} - -impl NeedsParentheses for ExprJoinedStr { - fn needs_parentheses( - &self, - _parent: AnyNodeRef, - _context: &PyFormatContext, - ) -> OptionalParentheses { - OptionalParentheses::Multiline - } -} diff --git a/crates/ruff_python_formatter/src/expression/expr_lambda.rs b/crates/ruff_python_formatter/src/expression/expr_lambda.rs index 858b7fbeaf818..b7d7d39b60611 100644 --- a/crates/ruff_python_formatter/src/expression/expr_lambda.rs +++ b/crates/ruff_python_formatter/src/expression/expr_lambda.rs @@ -1,14 +1,15 @@ -use crate::comments::dangling_node_comments; -use crate::context::PyFormatContext; -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; -use crate::other::arguments::ArgumentsParentheses; -use crate::AsFormat; -use crate::{FormatNodeRule, PyFormatter}; use ruff_formatter::prelude::{space, text}; use ruff_formatter::{write, Buffer, FormatResult}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::ExprLambda; +use crate::comments::{dangling_comments, SourceComment}; +use crate::context::PyFormatContext; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::other::parameters::ParametersParentheses; +use crate::AsFormat; +use crate::{FormatNodeRule, PyFormatter}; + #[derive(Default)] pub struct FormatExprLambda; @@ -16,40 +17,43 @@ impl FormatNodeRule for FormatExprLambda { fn fmt_fields(&self, item: &ExprLambda, f: &mut PyFormatter) -> FormatResult<()> { let ExprLambda { range: _, - args, + parameters, body, } = item; + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + write!(f, [text("lambda")])?; - if !args.args.is_empty() { + if let Some(parameters) = parameters { write!( f, [ space(), - args.format().with_options(ArgumentsParentheses::Never), + parameters + .format() + .with_options(ParametersParentheses::Never), ] )?; } - write!( - f, - [ - text(":"), - space(), - body.format(), - // It's possible for some `Arguments` of `lambda`s to be assigned dangling comments. - // - // a = ( - // lambda # Dangling - // : 1 - // ) - dangling_node_comments(args.as_ref()) - ] - ) + write!(f, [text(":")])?; + + if dangling.is_empty() { + write!(f, [space()])?; + } else { + write!(f, [dangling_comments(dangling)])?; + } + + write!(f, [body.format()]) } - fn fmt_dangling_comments(&self, _node: &ExprLambda, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Override. Dangling comments are handled in `fmt_fields`. Ok(()) } diff --git a/crates/ruff_python_formatter/src/expression/expr_list.rs b/crates/ruff_python_formatter/src/expression/expr_list.rs index 85fa33326a938..47e0a8353552b 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list.rs @@ -1,10 +1,14 @@ -use crate::builders::empty_parenthesized_with_dangling_comments; -use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; -use crate::prelude::*; -use crate::FormatNodeRule; +use crate::comments::SourceComment; +use ruff_formatter::prelude::format_with; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::{ExprList, Ranged}; +use crate::expression::parentheses::{ + empty_parenthesized, parenthesized, NeedsParentheses, OptionalParentheses, +}; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatExprList; @@ -17,28 +21,28 @@ impl FormatNodeRule for FormatExprList { } = item; let comments = f.context().comments().clone(); - let dangling = comments.dangling_comments(item); + let dangling = comments.dangling(item); if elts.is_empty() { - return empty_parenthesized_with_dangling_comments(text("["), dangling, text("]")) - .fmt(f); + return empty_parenthesized("[", dangling, "]").fmt(f); } - debug_assert!( - dangling.is_empty(), - "A non-empty expression list has dangling comments" - ); - let items = format_with(|f| { f.join_comma_separated(item.end()) .nodes(elts.iter()) .finish() }); - parenthesized("[", &items, "]").fmt(f) + parenthesized("[", &items, "]") + .with_dangling_comments(dangling) + .fmt(f) } - fn fmt_dangling_comments(&self, _node: &ExprList, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled as part of `fmt_fields` Ok(()) } diff --git a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs index 4763f6b4ee430..703126466c39c 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs @@ -1,11 +1,13 @@ +use ruff_formatter::{format_args, write, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::ExprListComp; + +use crate::comments::SourceComment; use crate::context::PyFormatContext; use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; use crate::prelude::*; use crate::AsFormat; use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::{format_args, write, Buffer, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::ExprListComp; #[derive(Default)] pub struct FormatExprListComp; @@ -24,6 +26,9 @@ impl FormatNodeRule for FormatExprListComp { .finish() }); + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + write!( f, [parenthesized( @@ -31,12 +36,22 @@ impl FormatNodeRule for FormatExprListComp { &group(&format_args![ group(&elt.format()), soft_line_break_or_space(), - group(&joined) + joined ]), "]" - )] + ) + .with_dangling_comments(dangling)] ) } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) + } } impl NeedsParentheses for ExprListComp { diff --git a/crates/ruff_python_formatter/src/expression/expr_name.rs b/crates/ruff_python_formatter/src/expression/expr_name.rs index e9aba4f8884cc..acfd88aad23ca 100644 --- a/crates/ruff_python_formatter/src/expression/expr_name.rs +++ b/crates/ruff_python_formatter/src/expression/expr_name.rs @@ -1,4 +1,5 @@ -use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::comments::SourceComment; +use crate::expression::parentheses::{should_use_best_fit, NeedsParentheses, OptionalParentheses}; use crate::prelude::*; use crate::FormatNodeRule; use ruff_formatter::{write, FormatContext}; @@ -22,27 +23,40 @@ impl FormatNodeRule for FormatExprName { write!(f, [source_text_slice(*range, ContainsNewlines::No)]) } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Node cannot have dangling comments + Ok(()) + } } impl NeedsParentheses for ExprName { fn needs_parentheses( &self, _parent: AnyNodeRef, - _context: &PyFormatContext, + context: &PyFormatContext, ) -> OptionalParentheses { - OptionalParentheses::Never + if should_use_best_fit(self, context) { + OptionalParentheses::BestFit + } else { + OptionalParentheses::Never + } } } #[cfg(test)] mod tests { - use ruff_python_ast::{ModModule, Ranged}; - use ruff_python_parser::Parse; + use ruff_python_ast::Ranged; + use ruff_python_parser::parse_program; use ruff_text_size::{TextRange, TextSize}; #[test] fn name_range_with_comments() { - let source = ModModule::parse("a # comment", "file.py").unwrap(); + let source = parse_program("a # comment", "file.py").unwrap(); let expression_statement = source .body diff --git a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs index 88bf4b2052619..98aeb4ceff41e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs +++ b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs @@ -1,7 +1,10 @@ +use crate::comments::{dangling_comments, SourceComment}; use crate::context::PyFormatContext; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; use crate::{AsFormat, FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{space, text}; +use ruff_formatter::prelude::{ + format_args, group, hard_line_break, soft_line_break_or_space, space, text, +}; use ruff_formatter::{write, Buffer, FormatResult}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::ExprNamedExpr; @@ -16,16 +19,35 @@ impl FormatNodeRule for FormatExprNamedExpr { value, range: _, } = item; + + // This context, a dangling comment is an end-of-line comment on the same line as the `:=`. + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + write!( f, [ - target.format(), - space(), - text(":="), - space(), - value.format(), + group(&format_args!(target.format(), soft_line_break_or_space())), + text(":=") ] - ) + )?; + + if dangling.is_empty() { + write!(f, [space()])?; + } else { + write!(f, [dangling_comments(dangling), hard_line_break()])?; + } + + write!(f, [value.format()]) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled by `fmt_fields` + Ok(()) } } @@ -44,13 +66,16 @@ impl NeedsParentheses for ExprNamedExpr { || parent.is_stmt_return() || parent.is_except_handler_except_handler() || parent.is_with_item() + || parent.is_expr_yield() + || parent.is_expr_yield_from() + || parent.is_expr_await() || parent.is_stmt_delete() || parent.is_stmt_for() - || parent.is_stmt_async_for() + || parent.is_stmt_function_def() { OptionalParentheses::Always } else { - OptionalParentheses::Never + OptionalParentheses::Multiline } } } diff --git a/crates/ruff_python_formatter/src/expression/expr_set.rs b/crates/ruff_python_formatter/src/expression/expr_set.rs index 8d3ffa17e984f..5027b46380fab 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set.rs @@ -1,6 +1,6 @@ -use ruff_python_ast::{ExprSet, Ranged}; - +use crate::comments::SourceComment; use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{ExprSet, Ranged}; use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; use crate::prelude::*; @@ -21,7 +21,21 @@ impl FormatNodeRule for FormatExprSet { .finish() }); - parenthesized("{", &joined, "}").fmt(f) + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + parenthesized("{", &joined, "}") + .with_dangling_comments(dangling) + .fmt(f) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs index 71704a33c6f8c..eb31a346a794d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs @@ -1,11 +1,13 @@ +use ruff_formatter::{format_args, write, Buffer, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::ExprSetComp; + +use crate::comments::SourceComment; use crate::context::PyFormatContext; use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; use crate::prelude::*; use crate::AsFormat; use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::{format_args, write, Buffer, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::ExprSetComp; #[derive(Default)] pub struct FormatExprSetComp; @@ -24,6 +26,9 @@ impl FormatNodeRule for FormatExprSetComp { .finish() }); + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + write!( f, [parenthesized( @@ -31,12 +36,22 @@ impl FormatNodeRule for FormatExprSetComp { &group(&format_args!( group(&elt.format()), soft_line_break_or_space(), - group(&joined) + joined )), "}" - )] + ) + .with_dangling_comments(dangling)] ) } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) + } } impl NeedsParentheses for ExprSetComp { diff --git a/crates/ruff_python_formatter/src/expression/expr_slice.rs b/crates/ruff_python_formatter/src/expression/expr_slice.rs index c26cd0508fc2f..ea23e41cdc979 100644 --- a/crates/ruff_python_formatter/src/expression/expr_slice.rs +++ b/crates/ruff_python_formatter/src/expression/expr_slice.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::{Expr, ExprSlice, ExprUnaryOp, Ranged, UnaryOp}; +use ruff_python_ast::{Expr, ExprSlice, ExprUnaryOp, UnaryOp}; use ruff_text_size::TextRange; use ruff_formatter::prelude::{hard_line_break, line_suffix_boundary, space, text}; @@ -20,13 +20,18 @@ impl FormatNodeRule for FormatExprSlice { fn fmt_fields(&self, item: &ExprSlice, f: &mut PyFormatter) -> FormatResult<()> { // `[lower:upper:step]` let ExprSlice { - range, lower, upper, step, + range, } = item; - let (first_colon, second_colon) = find_colons(f.context().source(), *range, lower, upper)?; + let (first_colon, second_colon) = find_colons( + f.context().source(), + *range, + lower.as_deref(), + upper.as_deref(), + )?; // Handle comment placement // In placements.rs, we marked comment for None nodes a dangling and associated all others @@ -34,16 +39,16 @@ impl FormatNodeRule for FormatExprSlice { // to handle newlines and spacing, or the node is None and we insert the corresponding // slice of dangling comments let comments = f.context().comments().clone(); - let slice_dangling_comments = comments.dangling_comments(item.as_any_node_ref()); + let slice_dangling_comments = comments.dangling(item.as_any_node_ref()); // Put the dangling comments (where the nodes are missing) into buckets - let first_colon_partition_index = slice_dangling_comments - .partition_point(|x| x.slice().start() < first_colon.range.start()); + let first_colon_partition_index = + slice_dangling_comments.partition_point(|x| x.slice().start() < first_colon.start()); let (dangling_lower_comments, dangling_upper_step_comments) = slice_dangling_comments.split_at(first_colon_partition_index); let (dangling_upper_comments, dangling_step_comments) = if let Some(second_colon) = &second_colon { let second_colon_partition_index = dangling_upper_step_comments - .partition_point(|x| x.slice().start() < second_colon.range.start()); + .partition_point(|x| x.slice().start() < second_colon.start()); dangling_upper_step_comments.split_at(second_colon_partition_index) } else { // Without a second colon they remaining dangling comments belong between the first @@ -97,7 +102,7 @@ impl FormatNodeRule for FormatExprSlice { // Upper if let Some(upper) = upper { - let upper_leading_comments = comments.leading_comments(upper.as_ref()); + let upper_leading_comments = comments.leading(upper.as_ref()); leading_comments_spacing(f, upper_leading_comments)?; write!(f, [upper.format(), line_suffix_boundary()])?; } else { @@ -129,7 +134,7 @@ impl FormatNodeRule for FormatExprSlice { space().fmt(f)?; } if let Some(step) = step { - let step_leading_comments = comments.leading_comments(step.as_ref()); + let step_leading_comments = comments.leading(step.as_ref()); leading_comments_spacing(f, step_leading_comments)?; step.format().fmt(f)?; } else if !dangling_step_comments.is_empty() { @@ -153,27 +158,27 @@ impl FormatNodeRule for FormatExprSlice { pub(crate) fn find_colons( contents: &str, range: TextRange, - lower: &Option>, - upper: &Option>, + lower: Option<&Expr>, + upper: Option<&Expr>, ) -> FormatResult<(SimpleToken, Option)> { let after_lower = lower .as_ref() - .map_or(range.start(), |lower| lower.range().end()); + .map_or(range.start(), ruff_python_ast::Ranged::end); let mut tokens = SimpleTokenizer::new(contents, TextRange::new(after_lower, range.end())) .skip_trivia() .skip_while(|token| token.kind == SimpleTokenKind::RParen); let first_colon = tokens.next().ok_or(FormatError::syntax_error( - "Din't find any token for slice first colon", + "Didn't find any token for slice first colon", ))?; if first_colon.kind != SimpleTokenKind::Colon { return Err(FormatError::syntax_error( - "slice first colon token was not a colon", + "Slice first colon token was not a colon", )); } let after_upper = upper .as_ref() - .map_or(first_colon.end(), |upper| upper.range().end()); + .map_or(first_colon.end(), ruff_python_ast::Ranged::end); let mut tokens = SimpleTokenizer::new(contents, TextRange::new(after_upper, range.end())) .skip_trivia() .skip_while(|token| token.kind == SimpleTokenKind::RParen); @@ -206,6 +211,7 @@ fn is_simple_expr(expr: &Expr) -> bool { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum ExprSliceCommentSection { Lower, Upper, @@ -229,21 +235,22 @@ pub(crate) fn assign_comment_in_slice( expr_slice: &ExprSlice, ) -> ExprSliceCommentSection { let ExprSlice { - range, lower, upper, step: _, + range, } = expr_slice; - let (first_colon, second_colon) = find_colons(contents, *range, lower, upper) - .expect("SyntaxError when trying to parse slice"); + let (first_colon, second_colon) = + find_colons(contents, *range, lower.as_deref(), upper.as_deref()) + .expect("SyntaxError when trying to parse slice"); - if comment.start() < first_colon.range.start() { + if comment.start() < first_colon.start() { ExprSliceCommentSection::Lower } else { // We are to the right of the first colon if let Some(second_colon) = second_colon { - if comment.start() < second_colon.range.start() { + if comment.start() < second_colon.start() { ExprSliceCommentSection::Upper } else { ExprSliceCommentSection::Step diff --git a/crates/ruff_python_formatter/src/expression/expr_starred.rs b/crates/ruff_python_formatter/src/expression/expr_starred.rs index 6f3e7723f304a..42ee9f7999ae4 100644 --- a/crates/ruff_python_formatter/src/expression/expr_starred.rs +++ b/crates/ruff_python_formatter/src/expression/expr_starred.rs @@ -1,5 +1,6 @@ use ruff_python_ast::ExprStarred; +use crate::comments::{dangling_comments, SourceComment}; use ruff_formatter::write; use ruff_python_ast::node::AnyNodeRef; @@ -19,12 +20,17 @@ impl FormatNodeRule for FormatExprStarred { ctx: _, } = item; - write!(f, [text("*"), value.format()]) - } + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); - fn fmt_dangling_comments(&self, node: &ExprStarred, f: &mut PyFormatter) -> FormatResult<()> { - debug_assert_eq!(f.context().comments().dangling_comments(node), []); + write!(f, [text("*"), dangling_comments(dangling), value.format()]) + } + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { Ok(()) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_subscript.rs b/crates/ruff_python_formatter/src/expression/expr_subscript.rs index 464028c2e1a60..169fbe9c4a50c 100644 --- a/crates/ruff_python_formatter/src/expression/expr_subscript.rs +++ b/crates/ruff_python_formatter/src/expression/expr_subscript.rs @@ -1,18 +1,29 @@ -use ruff_python_ast::{Expr, ExprSubscript}; - -use ruff_formatter::{format_args, write}; +use ruff_formatter::{format_args, write, FormatRuleWithOptions}; use ruff_python_ast::node::{AnyNodeRef, AstNode}; +use ruff_python_ast::{Expr, ExprSubscript}; -use crate::comments::trailing_comments; +use crate::comments::{trailing_comments, SourceComment}; use crate::context::PyFormatContext; use crate::context::{NodeLevel, WithNodeLevel}; use crate::expression::expr_tuple::TupleParentheses; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::expression::CallChainLayout; use crate::prelude::*; use crate::FormatNodeRule; #[derive(Default)] -pub struct FormatExprSubscript; +pub struct FormatExprSubscript { + call_chain_layout: CallChainLayout, +} + +impl FormatRuleWithOptions> for FormatExprSubscript { + type Options = CallChainLayout; + + fn with_options(mut self, options: Self::Options) -> Self { + self.call_chain_layout = options; + self + } +} impl FormatNodeRule for FormatExprSubscript { fn fmt_fields(&self, item: &ExprSubscript, f: &mut PyFormatter) -> FormatResult<()> { @@ -23,19 +34,28 @@ impl FormatNodeRule for FormatExprSubscript { ctx: _, } = item; + let call_chain_layout = self.call_chain_layout.apply_in_node(item, f); + let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(item.as_any_node_ref()); + let dangling_comments = comments.dangling(item.as_any_node_ref()); debug_assert!( dangling_comments.len() <= 1, "A subscript expression can only have a single dangling comment, the one after the bracket" ); + let format_value = format_with(|f| match value.as_ref() { + Expr::Attribute(expr) => expr.format().with_options(call_chain_layout).fmt(f), + Expr::Call(expr) => expr.format().with_options(call_chain_layout).fmt(f), + Expr::Subscript(expr) => expr.format().with_options(call_chain_layout).fmt(f), + _ => value.format().fmt(f), + }); + if let NodeLevel::Expression(Some(_)) = f.context().node_level() { // Enforce the optional parentheses for parenthesized values. let mut f = WithNodeLevel::new(NodeLevel::Expression(None), f); - write!(f, [value.format()])?; + write!(f, [format_value])?; } else { - value.format().fmt(f)?; + format_value.fmt(f)?; } let format_slice = format_with(|f: &mut PyFormatter| { @@ -61,7 +81,7 @@ impl FormatNodeRule for FormatExprSubscript { fn fmt_dangling_comments( &self, - _node: &ExprSubscript, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { // Handled inside of `fmt_fields` @@ -73,10 +93,19 @@ impl NeedsParentheses for ExprSubscript { fn needs_parentheses( &self, _parent: AnyNodeRef, - _context: &PyFormatContext, + context: &PyFormatContext, ) -> OptionalParentheses { { - OptionalParentheses::Never + if CallChainLayout::from_expression(self.into(), context.source()) + == CallChainLayout::Fluent + { + OptionalParentheses::Multiline + } else { + match self.value.needs_parentheses(self.into(), context) { + OptionalParentheses::BestFit => OptionalParentheses::Never, + parentheses => parentheses, + } + } } } } diff --git a/crates/ruff_python_formatter/src/expression/expr_tuple.rs b/crates/ruff_python_formatter/src/expression/expr_tuple.rs index 7a4e3dee3704d..94d93f373f5c7 100644 --- a/crates/ruff_python_formatter/src/expression/expr_tuple.rs +++ b/crates/ruff_python_formatter/src/expression/expr_tuple.rs @@ -1,15 +1,18 @@ -use ruff_python_ast::ExprTuple; -use ruff_python_ast::{Expr, Ranged}; -use ruff_text_size::TextRange; - use ruff_formatter::{format_args, write, FormatRuleWithOptions}; use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::ExprTuple; +use ruff_python_ast::Ranged; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::TextRange; -use crate::builders::{empty_parenthesized_with_dangling_comments, parenthesize_if_expands}; -use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses}; +use crate::builders::parenthesize_if_expands; +use crate::comments::SourceComment; +use crate::expression::parentheses::{ + empty_parenthesized, optional_parentheses, parenthesized, NeedsParentheses, OptionalParentheses, +}; use crate::prelude::*; -#[derive(Eq, PartialEq, Debug, Default)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] pub enum TupleParentheses { /// By default tuples with a single element will include parentheses. Tuples with multiple elements /// will parenthesize if the expression expands. This means that tuples will often *preserve* @@ -31,7 +34,6 @@ pub enum TupleParentheses { /// Handle the special cases where we don't include parentheses at all. /// - /// /// Black never formats tuple targets of for loops with parentheses if inside a comprehension. /// For example, tuple targets will always be formatted on the same line, except when an element supports /// line-breaking in an un-parenthesized context. @@ -99,11 +101,14 @@ impl FormatRuleWithOptions> for FormatExprTuple { impl FormatNodeRule for FormatExprTuple { fn fmt_fields(&self, item: &ExprTuple, f: &mut PyFormatter) -> FormatResult<()> { let ExprTuple { - range, elts, ctx: _, + range: _, } = item; + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + // Handle the edge cases of an empty tuple and a tuple with one element // // there can be dangling comments, and they can be in two @@ -116,35 +121,34 @@ impl FormatNodeRule for FormatExprTuple { // In all other cases comments get assigned to a list element match elts.as_slice() { [] => { - let comments = f.context().comments().clone(); - return empty_parenthesized_with_dangling_comments( - text("("), - comments.dangling_comments(item), - text(")"), - ) - .fmt(f); + return empty_parenthesized("(", dangling, ")").fmt(f); } [single] => match self.parentheses { TupleParentheses::Preserve - if !is_parenthesized(*range, elts, f.context().source()) => + if !is_tuple_parenthesized(item, f.context().source()) => { write!(f, [single.format(), text(",")]) } _ => // A single element tuple always needs parentheses and a trailing comma, except when inside of a subscript { - parenthesized("(", &format_args![single.format(), text(",")], ")").fmt(f) + parenthesized("(", &format_args![single.format(), text(",")], ")") + .with_dangling_comments(dangling) + .fmt(f) } }, // If the tuple has parentheses, we generally want to keep them. The exception are for - // loops, see `TupleParentheses::StripInsideForLoop` doc comment. + // loops, see `TupleParentheses::NeverPreserve` doc comment. // // Unlike other expression parentheses, tuple parentheses are part of the range of the // tuple itself. - _ if is_parenthesized(*range, elts, f.context().source()) - && self.parentheses != TupleParentheses::NeverPreserve => + _ if is_tuple_parenthesized(item, f.context().source()) + && !(self.parentheses == TupleParentheses::NeverPreserve + && dangling.is_empty()) => { - parenthesized("(", &ExprSequence::new(item), ")").fmt(f) + parenthesized("(", &ExprSequence::new(item), ")") + .with_dangling_comments(dangling) + .fmt(f) } _ => match self.parentheses { TupleParentheses::Never => { @@ -155,12 +159,21 @@ impl FormatNodeRule for FormatExprTuple { .finish() } TupleParentheses::Preserve => group(&ExprSequence::new(item)).fmt(f), - _ => parenthesize_if_expands(&ExprSequence::new(item)).fmt(f), + TupleParentheses::NeverPreserve => { + optional_parentheses(&ExprSequence::new(item)).fmt(f) + } + TupleParentheses::Default => { + parenthesize_if_expands(&ExprSequence::new(item)).fmt(f) + } }, } } - fn fmt_dangling_comments(&self, _node: &ExprTuple, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled in `fmt_fields` Ok(()) } @@ -178,7 +191,7 @@ impl<'a> ExprSequence<'a> { } impl Format> for ExprSequence<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { f.join_comma_separated(self.tuple.end()) .nodes(&self.tuple.elts) .finish() @@ -196,21 +209,30 @@ impl NeedsParentheses for ExprTuple { } /// Check if a tuple has already had parentheses in the input -fn is_parenthesized(tuple_range: TextRange, elts: &[Expr], source: &str) -> bool { - let parentheses = '('; - let first_char = &source[usize::from(tuple_range.start())..].chars().next(); - let Some(first_char) = first_char else { +pub(crate) fn is_tuple_parenthesized(tuple: &ExprTuple, source: &str) -> bool { + let Some(elt) = tuple.elts.first() else { return false; }; - if *first_char != parentheses { + + // Count the number of open parentheses between the start of the tuple and the first element. + let open_parentheses_count = + SimpleTokenizer::new(source, TextRange::new(tuple.start(), elt.start())) + .skip_trivia() + .filter(|token| token.kind() == SimpleTokenKind::LParen) + .count(); + if open_parentheses_count == 0 { return false; } - // Consider `a = (1, 2), 3`: The first char of the current expr starts is a parentheses, but - // it's not its own but that of its first tuple child. We know that it belongs to the child - // because if it wouldn't, the child would start (at least) a char later - let Some(first_child) = elts.first() else { - return false; - }; - first_child.range().start() != tuple_range.start() + // Count the number of parentheses between the end of the first element and its trailing comma. + let close_parentheses_count = + SimpleTokenizer::new(source, TextRange::new(elt.end(), tuple.end())) + .skip_trivia() + .take_while(|token| token.kind() != SimpleTokenKind::Comma) + .filter(|token| token.kind() == SimpleTokenKind::RParen) + .count(); + + // If the number of open parentheses is greater than the number of close parentheses, the tuple + // is parenthesized. + open_parentheses_count > close_parentheses_count } diff --git a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs index 2e1919e180b98..971f7a2d09d46 100644 --- a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs @@ -3,7 +3,7 @@ use ruff_python_ast::{ExprUnaryOp, Ranged}; use ruff_text_size::{TextLen, TextRange}; use ruff_formatter::prelude::{hard_line_break, space, text}; -use ruff_formatter::{Format, FormatContext, FormatResult}; +use ruff_formatter::{Format, FormatResult}; use ruff_python_ast::node::AnyNodeRef; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; @@ -39,7 +39,7 @@ impl FormatNodeRule for FormatExprUnaryOp { // (not # comment // a) // ``` - let leading_operand_comments = comments.leading_comments(operand.as_ref()); + let leading_operand_comments = comments.leading(operand.as_ref()); let trailing_operator_comments_end = leading_operand_comments.partition_point(|p| p.line_position().is_end_of_line()); let (trailing_operator_comments, leading_operand_comments) = @@ -57,7 +57,7 @@ impl FormatNodeRule for FormatExprUnaryOp { // a) // ``` if !leading_operand_comments.is_empty() - && !is_operand_parenthesized(item, f.context().source_code().as_str()) + && !is_operand_parenthesized(item, f.context().source()) { hard_line_break().fmt(f)?; } else if op.is_not() { @@ -91,7 +91,7 @@ fn is_operand_parenthesized(unary: &ExprUnaryOp, source: &str) -> bool { UnaryOp::USub => '-'.text_len(), }; - let trivia_range = TextRange::new(unary.range.start() + operator_len, unary.operand.start()); + let trivia_range = TextRange::new(unary.start() + operator_len, unary.operand.start()); if let Some(token) = SimpleTokenizer::new(source, trivia_range) .skip_trivia() diff --git a/crates/ruff_python_formatter/src/expression/expr_yield.rs b/crates/ruff_python_formatter/src/expression/expr_yield.rs index 92581a3f9c02c..077d0eaa89579 100644 --- a/crates/ruff_python_formatter/src/expression/expr_yield.rs +++ b/crates/ruff_python_formatter/src/expression/expr_yield.rs @@ -77,7 +77,7 @@ impl<'a> From<&AnyExpressionYield<'a>> for AnyNodeRef<'a> { } impl Format> for AnyExpressionYield<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let keyword = if self.is_yield_from() { "yield from" } else { @@ -90,7 +90,7 @@ impl Format> for AnyExpressionYield<'_> { [ text(keyword), space(), - maybe_parenthesize_expression(val, self, Parenthesize::IfRequired) + maybe_parenthesize_expression(val, self, Parenthesize::Optional) ] )?; } else { diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index a7c395eb041bd..e71e803079197 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -1,15 +1,16 @@ +use itertools::Itertools; use std::cmp::Ordering; -use ruff_python_ast as ast; -use ruff_python_ast::{Expr, Operator}; - use ruff_formatter::{ - write, FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions, + format_args, write, FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions, }; +use ruff_python_ast as ast; use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::preorder::{walk_expr, PreorderVisitor}; +use ruff_python_ast::{Expr, ExpressionRef, Operator}; use crate::builders::parenthesize_if_expands; +use crate::comments::leading_comments; use crate::context::{NodeLevel, WithNodeLevel}; use crate::expression::parentheses::{ is_expression_parenthesized, optional_parentheses, parenthesized, NeedsParentheses, @@ -26,10 +27,11 @@ pub(crate) mod expr_compare; pub(crate) mod expr_constant; pub(crate) mod expr_dict; pub(crate) mod expr_dict_comp; +pub(crate) mod expr_f_string; pub(crate) mod expr_formatted_value; pub(crate) mod expr_generator_exp; pub(crate) mod expr_if_exp; -pub(crate) mod expr_joined_str; +pub(crate) mod expr_ipy_escape_command; pub(crate) mod expr_lambda; pub(crate) mod expr_list; pub(crate) mod expr_list_comp; @@ -67,9 +69,9 @@ impl FormatRule> for FormatExpr { let parentheses = self.parentheses; let format_expr = format_with(|f| match expression { - Expr::BoolOp(expr) => expr.format().with_options(Some(parentheses)).fmt(f), + Expr::BoolOp(expr) => expr.format().fmt(f), Expr::NamedExpr(expr) => expr.format().fmt(f), - Expr::BinOp(expr) => expr.format().with_options(Some(parentheses)).fmt(f), + Expr::BinOp(expr) => expr.format().fmt(f), Expr::UnaryOp(expr) => expr.format().fmt(f), Expr::Lambda(expr) => expr.format().fmt(f), Expr::IfExp(expr) => expr.format().fmt(f), @@ -82,10 +84,10 @@ impl FormatRule> for FormatExpr { Expr::Await(expr) => expr.format().fmt(f), Expr::Yield(expr) => expr.format().fmt(f), Expr::YieldFrom(expr) => expr.format().fmt(f), - Expr::Compare(expr) => expr.format().with_options(Some(parentheses)).fmt(f), + Expr::Compare(expr) => expr.format().fmt(f), Expr::Call(expr) => expr.format().fmt(f), Expr::FormattedValue(expr) => expr.format().fmt(f), - Expr::JoinedStr(expr) => expr.format().fmt(f), + Expr::FString(expr) => expr.format().fmt(f), Expr::Constant(expr) => expr.format().fmt(f), Expr::Attribute(expr) => expr.format().fmt(f), Expr::Subscript(expr) => expr.format().fmt(f), @@ -94,19 +96,44 @@ impl FormatRule> for FormatExpr { Expr::List(expr) => expr.format().fmt(f), Expr::Tuple(expr) => expr.format().fmt(f), Expr::Slice(expr) => expr.format().fmt(f), - Expr::LineMagic(_) => todo!(), + Expr::IpyEscapeCommand(expr) => expr.format().fmt(f), }); let parenthesize = match parentheses { Parentheses::Preserve => { - is_expression_parenthesized(AnyNodeRef::from(expression), f.context().source()) + is_expression_parenthesized(expression.into(), f.context().source()) } Parentheses::Always => true, + // Fluent style means we already have parentheses Parentheses::Never => false, }; if parenthesize { - parenthesized("(", &format_expr, ")").fmt(f) + // Any comments on the open parenthesis of a `node`. + // + // For example, `# comment` in: + // ```python + // ( # comment + // foo.bar + // ) + // ``` + let comments = f.context().comments().clone(); + let leading = comments.leading(expression); + if let Some((index, open_parenthesis_comment)) = leading + .iter() + .find_position(|comment| comment.line_position().is_end_of_line()) + { + write!( + f, + [ + leading_comments(&leading[..index]), + parenthesized("(", &format_expr, ")") + .with_dangling_comments(std::slice::from_ref(open_parenthesis_comment)) + ] + ) + } else { + parenthesized("(", &format_expr, ")").fmt(f) + } } else { let level = match f.context().node_level() { NodeLevel::TopLevel | NodeLevel::CompoundStatement => NodeLevel::Expression(None), @@ -147,7 +174,7 @@ pub(crate) struct MaybeParenthesizeExpression<'a> { } impl Format> for MaybeParenthesizeExpression<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let MaybeParenthesizeExpression { expression, parent, @@ -156,43 +183,120 @@ impl Format> for MaybeParenthesizeExpression<'_> { let comments = f.context().comments(); let preserve_parentheses = parenthesize.is_optional() - && is_expression_parenthesized(AnyNodeRef::from(*expression), f.context().source()); + && is_expression_parenthesized((*expression).into(), f.context().source()); - let has_comments = comments.has_leading_comments(*expression) - || comments.has_trailing_own_line_comments(*expression); + let has_comments = + comments.has_leading(*expression) || comments.has_trailing_own_line(*expression); + // If the expression has comments, we always want to preserve the parentheses. This also + // ensures that we correctly handle parenthesized comments, and don't need to worry about + // them in the implementation below. if preserve_parentheses || has_comments { return expression.format().with_options(Parentheses::Always).fmt(f); } - let needs_parentheses = expression.needs_parentheses(*parent, f.context()); - let needs_parentheses = match parenthesize { - Parenthesize::IfRequired => { - if !needs_parentheses.is_always() && f.context().node_level().is_parenthesized() { - OptionalParentheses::Never - } else { - needs_parentheses - } - } - Parenthesize::Optional | Parenthesize::IfBreaks => needs_parentheses, + let needs_parentheses = match expression.needs_parentheses(*parent, f.context()) { + OptionalParentheses::Always => OptionalParentheses::Always, + // The reason to add parentheses is to avoid a syntax error when breaking an expression over multiple lines. + // Therefore, it is unnecessary to add an additional pair of parentheses if an outer expression + // is parenthesized. + _ if f.context().node_level().is_parenthesized() => OptionalParentheses::Never, + needs_parentheses => needs_parentheses, }; match needs_parentheses { - OptionalParentheses::Multiline if *parenthesize != Parenthesize::IfRequired => { - if can_omit_optional_parentheses(expression, f.context()) { - optional_parentheses(&expression.format().with_options(Parentheses::Never)) + OptionalParentheses::Multiline => match parenthesize { + Parenthesize::IfBreaksOrIfRequired => { + parenthesize_if_expands(&expression.format().with_options(Parentheses::Never)) .fmt(f) - } else { + } + Parenthesize::IfRequired => { + expression.format().with_options(Parentheses::Never).fmt(f) + } + Parenthesize::Optional | Parenthesize::IfBreaks => { + if can_omit_optional_parentheses(expression, f.context()) { + optional_parentheses(&expression.format().with_options(Parentheses::Never)) + .fmt(f) + } else { + parenthesize_if_expands( + &expression.format().with_options(Parentheses::Never), + ) + .fmt(f) + } + } + }, + OptionalParentheses::BestFit => match parenthesize { + Parenthesize::IfBreaksOrIfRequired => { parenthesize_if_expands(&expression.format().with_options(Parentheses::Never)) .fmt(f) } - } + + Parenthesize::Optional | Parenthesize::IfRequired => { + expression.format().with_options(Parentheses::Never).fmt(f) + } + Parenthesize::IfBreaks => { + let group_id = f.group_id("optional_parentheses"); + let f = &mut WithNodeLevel::new(NodeLevel::Expression(Some(group_id)), f); + let mut format_expression = expression + .format() + .with_options(Parentheses::Never) + .memoized(); + + // Don't use best fitting if it is known that the expression can never fit + if format_expression.inspect(f)?.will_break() { + // The group here is necessary because `format_expression` may contain IR elements + // that refer to the group id + group(&format_expression) + .with_group_id(Some(group_id)) + .should_expand(true) + .fmt(f) + } else { + // Only add parentheses if it makes the expression fit on the line. + // Using the flat version as the most expanded version gives a left-to-right splitting behavior + // which differs from when using regular groups, because they split right-to-left. + best_fitting![ + // --------------------------------------------------------------------- + // Variant 1: + // Try to fit the expression without any parentheses + group(&format_expression).with_group_id(Some(group_id)), + // --------------------------------------------------------------------- + // Variant 2: + // Try to fit the expression by adding parentheses and indenting the expression. + group(&format_args![ + text("("), + soft_block_indent(&format_expression), + text(")") + ]) + .with_group_id(Some(group_id)) + .should_expand(true), + // --------------------------------------------------------------------- + // Variant 3: Fallback, no parentheses + // Expression doesn't fit regardless of adding the parentheses. Remove the parentheses again. + group(&format_expression) + .with_group_id(Some(group_id)) + .should_expand(true) + ] + // Measure all lines, to avoid that the printer decides that this fits right after hitting + // the `(`. + .with_mode(BestFittingMode::AllLines) + .fmt(f) + } + } + }, + OptionalParentheses::Never => match parenthesize { + Parenthesize::IfBreaksOrIfRequired => { + parenthesize_if_expands(&expression.format().with_options(Parentheses::Never)) + .fmt(f) + } + + Parenthesize::Optional | Parenthesize::IfBreaks | Parenthesize::IfRequired => { + expression.format().with_options(Parentheses::Never).fmt(f) + } + }, + OptionalParentheses::Always => { expression.format().with_options(Parentheses::Always).fmt(f) } - OptionalParentheses::Never | OptionalParentheses::Multiline => { - expression.format().with_options(Parentheses::Never).fmt(f) - } } } } @@ -222,7 +326,7 @@ impl NeedsParentheses for Expr { Expr::Compare(expr) => expr.needs_parentheses(parent, context), Expr::Call(expr) => expr.needs_parentheses(parent, context), Expr::FormattedValue(expr) => expr.needs_parentheses(parent, context), - Expr::JoinedStr(expr) => expr.needs_parentheses(parent, context), + Expr::FString(expr) => expr.needs_parentheses(parent, context), Expr::Constant(expr) => expr.needs_parentheses(parent, context), Expr::Attribute(expr) => expr.needs_parentheses(parent, context), Expr::Subscript(expr) => expr.needs_parentheses(parent, context), @@ -231,7 +335,7 @@ impl NeedsParentheses for Expr { Expr::List(expr) => expr.needs_parentheses(parent, context), Expr::Tuple(expr) => expr.needs_parentheses(parent, context), Expr::Slice(expr) => expr.needs_parentheses(parent, context), - Expr::LineMagic(_) => todo!(), + Expr::IpyEscapeCommand(_) => todo!(), } } } @@ -262,9 +366,29 @@ impl<'ast> IntoFormat> for Expr { /// /// This mimics Black's [`_maybe_split_omitting_optional_parens`](https://github.com/psf/black/blob/d1248ca9beaf0ba526d265f4108836d89cf551b7/src/black/linegen.py#L746-L820) fn can_omit_optional_parentheses(expr: &Expr, context: &PyFormatContext) -> bool { - let mut visitor = CanOmitOptionalParenthesesVisitor::new(context.source()); + let mut visitor = CanOmitOptionalParenthesesVisitor::new(context); visitor.visit_subexpression(expr); - visitor.can_omit() + + if visitor.max_priority == OperatorPriority::None { + true + } else if visitor.max_priority_count > 1 { + false + } else if visitor.max_priority == OperatorPriority::Attribute { + true + } else if !visitor.any_parenthesized_expressions { + // Only use the more complex IR when there is any expression that we can possibly split by + false + } else { + // Only use the layout if the first or last expression has parentheses of some sort, and + // those parentheses are non-empty. + let first_parenthesized = visitor.first.is_some_and(|first| { + has_parentheses(first, context).is_some_and(|parentheses| parentheses.is_non_empty()) + }); + let last_parenthesized = visitor.last.is_some_and(|last| { + has_parentheses(last, context).is_some_and(|parentheses| parentheses.is_non_empty()) + }); + first_parenthesized || last_parenthesized + } } #[derive(Clone, Debug)] @@ -274,13 +398,13 @@ struct CanOmitOptionalParenthesesVisitor<'input> { any_parenthesized_expressions: bool, last: Option<&'input Expr>, first: Option<&'input Expr>, - source: &'input str, + context: &'input PyFormatContext<'input>, } impl<'input> CanOmitOptionalParenthesesVisitor<'input> { - fn new(source: &'input str) -> Self { + fn new(context: &'input PyFormatContext) -> Self { Self { - source, + context, max_priority: OperatorPriority::None, max_priority_count: 0, any_parenthesized_expressions: false, @@ -356,8 +480,7 @@ impl<'input> CanOmitOptionalParenthesesVisitor<'input> { Expr::Call(ast::ExprCall { range: _, func, - args: _, - keywords: _, + arguments: _, }) => { self.any_parenthesized_expressions = true; // Only walk the function, the arguments are always parenthesized @@ -365,8 +488,10 @@ impl<'input> CanOmitOptionalParenthesesVisitor<'input> { self.last = Some(expr); return; } - Expr::Subscript(_) => { - // Don't walk the value. Splitting before the value looks weird. + Expr::Subscript(ast::ExprSubscript { value, .. }) => { + self.any_parenthesized_expressions = true; + // Only walk the function, the subscript is always parenthesized + self.visit_expr(value); // Don't walk the slice, because the slice is always parenthesized. return; } @@ -387,9 +512,12 @@ impl<'input> CanOmitOptionalParenthesesVisitor<'input> { attr: _, ctx: _, }) => { - if has_parentheses(value, self.source) { + self.visit_expr(value); + if has_parentheses(value, self.context).is_some() { self.update_max_priority(OperatorPriority::Attribute); } + self.last = Some(expr); + return; } Expr::NamedExpr(_) @@ -399,36 +527,16 @@ impl<'input> CanOmitOptionalParenthesesVisitor<'input> { | Expr::Yield(_) | Expr::YieldFrom(_) | Expr::FormattedValue(_) - | Expr::JoinedStr(_) + | Expr::FString(_) | Expr::Constant(_) | Expr::Starred(_) | Expr::Name(_) | Expr::Slice(_) => {} - Expr::LineMagic(_) => todo!(), + Expr::IpyEscapeCommand(_) => todo!(), }; walk_expr(self, expr); } - - fn can_omit(self) -> bool { - if self.max_priority_count > 1 { - false - } else if self.max_priority == OperatorPriority::Attribute { - true - } else if !self.any_parenthesized_expressions { - // Only use the more complex IR when there is any expression that we can possibly split by - false - } else { - // Only use the layout if the first or last expression has parentheses of some sort. - let first_parenthesized = self - .first - .map_or(false, |first| has_parentheses(first, self.source)); - let last_parenthesized = self - .last - .map_or(false, |last| has_parentheses(last, self.source)); - first_parenthesized || last_parenthesized - } - } } impl<'input> PreorderVisitor<'input> for CanOmitOptionalParenthesesVisitor<'input> { @@ -436,7 +544,7 @@ impl<'input> PreorderVisitor<'input> for CanOmitOptionalParenthesesVisitor<'inpu self.last = Some(expr); // Rule only applies for non-parenthesized expressions. - if is_expression_parenthesized(AnyNodeRef::from(expr), self.source) { + if is_expression_parenthesized(expr.into(), self.context.source()) { self.any_parenthesized_expressions = true; } else { self.visit_subexpression(expr); @@ -448,23 +556,201 @@ impl<'input> PreorderVisitor<'input> for CanOmitOptionalParenthesesVisitor<'inpu } } -fn has_parentheses(expr: &Expr, source: &str) -> bool { - has_own_parentheses(expr) || is_expression_parenthesized(AnyNodeRef::from(expr), source) +/// A call chain consists only of attribute access (`.` operator), function/method calls and +/// subscripts. We use fluent style for the call chain if there are at least two attribute dots +/// after call parentheses or subscript brackets. In case of fluent style the parentheses/bracket +/// will close on the previous line and the dot gets its own line, otherwise the line will start +/// with the closing parentheses/bracket and the dot follows immediately after. +/// +/// Below, the left hand side of the addition has only a single attribute access after a call, the +/// second `.filter`. The first `.filter` is a call, but it doesn't follow a call. The right hand +/// side has two, the `.limit_results` after the call and the `.filter` after the subscript, so it +/// gets formatted in fluent style. The outer expression we assign to `blogs` has zero since the +/// `.all` follows attribute parentheses and not call parentheses. +/// +/// ```python +/// blogs = ( +/// Blog.objects.filter( +/// entry__headline__contains="Lennon", +/// ).filter( +/// entry__pub_date__year=2008, +/// ) +/// + Blog.objects.filter( +/// entry__headline__contains="McCartney", +/// ) +/// .limit_results[:10] +/// .filter( +/// entry__pub_date__year=2010, +/// ) +/// ).all() +/// ``` +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum CallChainLayout { + /// The root of a call chain + #[default] + Default, + + /// A nested call chain element that uses fluent style. + Fluent, + + /// A nested call chain element not using fluent style. + NonFluent, +} + +impl CallChainLayout { + pub(crate) fn from_expression(mut expr: ExpressionRef, source: &str) -> Self { + let mut attributes_after_parentheses = 0; + loop { + match expr { + ExpressionRef::Attribute(ast::ExprAttribute { value, .. }) => { + expr = ExpressionRef::from(value.as_ref()); + // ``` + // f().g + // ^^^ value + // data[:100].T + // ^^^^^^^^^^ value + // ``` + if matches!(value.as_ref(), Expr::Call(_) | Expr::Subscript(_)) { + attributes_after_parentheses += 1; + } else if is_expression_parenthesized(expr, source) { + // `(a).b`. We preserve these parentheses so don't recurse + attributes_after_parentheses += 1; + break; + } + } + // ``` + // f() + // ^^^ expr + // ^ func + // data[:100] + // ^^^^^^^^^^ expr + // ^^^^ value + // ``` + ExpressionRef::Call(ast::ExprCall { func: inner, .. }) + | ExpressionRef::Subscript(ast::ExprSubscript { value: inner, .. }) => { + expr = ExpressionRef::from(inner.as_ref()); + } + _ => { + // We to format the following in fluent style: + // ``` + // f2 = (a).w().t(1,) + // ^ expr + // ``` + if is_expression_parenthesized(expr, source) { + attributes_after_parentheses += 1; + } + break; + } + } + // We preserve these parentheses so don't recurse + if is_expression_parenthesized(expr, source) { + break; + } + } + if attributes_after_parentheses < 2 { + CallChainLayout::NonFluent + } else { + CallChainLayout::Fluent + } + } + + /// Determine whether to actually apply fluent layout in attribute, call and subscript + /// formatting + pub(crate) fn apply_in_node<'a>( + self, + item: impl Into>, + f: &mut PyFormatter, + ) -> CallChainLayout { + match self { + CallChainLayout::Default => { + if f.context().node_level().is_parenthesized() { + CallChainLayout::from_expression(item.into(), f.context().source()) + } else { + CallChainLayout::NonFluent + } + } + layout @ (CallChainLayout::Fluent | CallChainLayout::NonFluent) => layout, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, is_macro::Is)] +pub(crate) enum OwnParentheses { + /// The node has parentheses, but they are empty (e.g., `[]` or `f()`). + Empty, + /// The node has parentheses, and they are non-empty (e.g., `[1]` or `f(1)`). + NonEmpty, } -pub(crate) const fn has_own_parentheses(expr: &Expr) -> bool { - matches!( - expr, - Expr::Dict(_) - | Expr::List(_) - | Expr::Tuple(_) - | Expr::Set(_) - | Expr::ListComp(_) - | Expr::SetComp(_) - | Expr::DictComp(_) - | Expr::Call(_) - | Expr::Subscript(_) - ) +/// Returns the [`OwnParentheses`] value for a given [`Expr`], to indicate whether it has its +/// own parentheses or is itself parenthesized. +/// +/// Differs from [`has_own_parentheses`] in that it returns [`OwnParentheses::NonEmpty`] for +/// parenthesized expressions, like `(1)` or `([1])`, regardless of whether those expression have +/// their _own_ parentheses. +fn has_parentheses(expr: &Expr, context: &PyFormatContext) -> Option { + let own_parentheses = has_own_parentheses(expr, context); + + // If the node has its own non-empty parentheses, we don't need to check for surrounding + // parentheses (e.g., `[1]`, or `([1])`). + if own_parentheses == Some(OwnParentheses::NonEmpty) { + return own_parentheses; + } + + // Otherwise, if the node lacks parentheses (e.g., `(1)`) or only contains empty parentheses + // (e.g., `([])`), we need to check for surrounding parentheses. + if is_expression_parenthesized(expr.into(), context.source()) { + return Some(OwnParentheses::NonEmpty); + } + + own_parentheses +} + +/// Returns the [`OwnParentheses`] value for a given [`Expr`], to indicate whether it has its +/// own parentheses, and whether those parentheses are empty. +/// +/// A node is considered to have its own parentheses if it includes a `[]`, `()`, or `{}` pair +/// that is inherent to the node (e.g., as in `f()`, `[]`, or `{1: 2}`, but not `(a.b.c)`). +/// +/// Parentheses are considered to be non-empty if they contain any elements or comments. +pub(crate) fn has_own_parentheses( + expr: &Expr, + context: &PyFormatContext, +) -> Option { + match expr { + // These expressions are always non-empty. + Expr::ListComp(_) | Expr::SetComp(_) | Expr::DictComp(_) | Expr::Subscript(_) => { + Some(OwnParentheses::NonEmpty) + } + + // These expressions must contain _some_ child or trivia token in order to be non-empty. + Expr::List(ast::ExprList { elts, .. }) + | Expr::Set(ast::ExprSet { elts, .. }) + | Expr::Tuple(ast::ExprTuple { elts, .. }) => { + if !elts.is_empty() || context.comments().has_dangling(AnyNodeRef::from(expr)) { + Some(OwnParentheses::NonEmpty) + } else { + Some(OwnParentheses::Empty) + } + } + + Expr::Dict(ast::ExprDict { keys, .. }) => { + if !keys.is_empty() || context.comments().has_dangling(AnyNodeRef::from(expr)) { + Some(OwnParentheses::NonEmpty) + } else { + Some(OwnParentheses::Empty) + } + } + Expr::Call(ast::ExprCall { arguments, .. }) => { + if !arguments.is_empty() || context.comments().has_dangling(AnyNodeRef::from(expr)) { + Some(OwnParentheses::NonEmpty) + } else { + Some(OwnParentheses::Empty) + } + } + + _ => None, + } } #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] diff --git a/crates/ruff_python_formatter/src/expression/number.rs b/crates/ruff_python_formatter/src/expression/number.rs index 92c67ffa7e806..3a5836dec010e 100644 --- a/crates/ruff_python_formatter/src/expression/number.rs +++ b/crates/ruff_python_formatter/src/expression/number.rs @@ -17,7 +17,7 @@ impl<'a> FormatInt<'a> { } impl Format> for FormatInt<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let range = self.constant.range(); let content = f.context().locator().slice(range); @@ -42,7 +42,7 @@ impl<'a> FormatFloat<'a> { } impl Format> for FormatFloat<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let range = self.constant.range(); let content = f.context().locator().slice(range); @@ -67,7 +67,7 @@ impl<'a> FormatComplex<'a> { } impl Format> for FormatComplex<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let range = self.constant.range(); let content = f.context().locator().slice(range); diff --git a/crates/ruff_python_formatter/src/expression/parentheses.rs b/crates/ruff_python_formatter/src/expression/parentheses.rs index abe7cc9d623c2..0ba3bc2a70779 100644 --- a/crates/ruff_python_formatter/src/expression/parentheses.rs +++ b/crates/ruff_python_formatter/src/expression/parentheses.rs @@ -1,10 +1,12 @@ -use ruff_python_ast::Ranged; - use ruff_formatter::prelude::tag::Condition; -use ruff_formatter::{format_args, write, Argument, Arguments}; +use ruff_formatter::{format_args, write, Argument, Arguments, FormatContext, FormatOptions}; use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{ExpressionRef, Ranged}; use ruff_python_trivia::{first_non_trivia_token, SimpleToken, SimpleTokenKind, SimpleTokenizer}; +use crate::comments::{ + dangling_comments, dangling_open_parenthesis_comments, trailing_comments, SourceComment, +}; use crate::context::{NodeLevel, WithNodeLevel}; use crate::prelude::*; @@ -13,18 +15,35 @@ pub(crate) enum OptionalParentheses { /// Add parentheses if the expression expands over multiple lines Multiline, - /// Always set parentheses regardless if the expression breaks or if they were + /// Always set parentheses regardless if the expression breaks or if they are /// present in the source. Always, - /// Never add parentheses + /// Add parentheses if it helps to make this expression fit. Otherwise never add parentheses. + /// This mode should only be used for expressions that don't have their own split points, e.g. identifiers, + /// or constants. + BestFit, + + /// Never add parentheses. Use it for expressions that have their own parentheses or if the expression body always spans multiple lines (multiline strings). Never, } -impl OptionalParentheses { - pub(crate) const fn is_always(self) -> bool { - matches!(self, OptionalParentheses::Always) - } +pub(super) fn should_use_best_fit(value: T, context: &PyFormatContext) -> bool +where + T: Ranged, +{ + let text_len = context.source()[value.range()].len(); + + // Only use best fits if: + // * The text is longer than 5 characters: + // This is to align the behavior with `True` and `False`, that don't use best fits and are 5 characters long. + // It allows to avoid [`OptionalParentheses::BestFit`] for most numbers and common identifiers like `self`. + // The downside is that it can result in short values not being parenthesized if they exceed the line width. + // This is considered an edge case not worth the performance penalty and IMO, breaking an identifier + // of 5 characters to avoid it exceeding the line width by 1 reduces the readability. + // * The text is know to never fit: The text can never fit even when parenthesizing if it is longer + // than the configured line width (minus indent). + text_len > 5 && text_len < context.options().line_width().value() as usize } pub(crate) trait NeedsParentheses { @@ -45,10 +64,14 @@ pub(crate) enum Parenthesize { /// Parenthesizes the expression only if it doesn't fit on a line. IfBreaks, - /// Only adds parentheses if absolutely necessary: - /// * The expression is not enclosed by another parenthesized expression and it expands over multiple lines - /// * The expression has leading or trailing comments. Adding parentheses is desired to prevent the comments from wandering. + /// Only adds parentheses if the expression has leading or trailing comments. + /// Adding parentheses is desired to prevent the comments from wandering. IfRequired, + + /// Parenthesizes the expression if the group doesn't fit on a line (e.g., even name expressions are parenthesized), or if + /// the expression doesn't break, but _does_ reports that it always requires parentheses in this position (e.g., walrus + /// operators in function return annotations). + IfBreaksOrIfRequired, } impl Parenthesize { @@ -73,7 +96,7 @@ pub enum Parentheses { Never, } -pub(crate) fn is_expression_parenthesized(expr: AnyNodeRef, contents: &str) -> bool { +pub(crate) fn is_expression_parenthesized(expr: ExpressionRef, contents: &str) -> bool { // First test if there's a closing parentheses because it tends to be cheaper. if matches!( first_non_trivia_token(expr.end(), contents), @@ -110,6 +133,7 @@ where { FormatParenthesized { left, + comments: &[], content: Argument::new(content), right, } @@ -117,16 +141,36 @@ where pub(crate) struct FormatParenthesized<'content, 'ast> { left: &'static str, + comments: &'content [SourceComment], content: Argument<'content, PyFormatContext<'ast>>, right: &'static str, } +impl<'content, 'ast> FormatParenthesized<'content, 'ast> { + /// Inserts any dangling comments that should be placed immediately after the open parenthesis. + /// For example: + /// ```python + /// [ # comment + /// 1, + /// 2, + /// 3, + /// ] + /// ``` + pub(crate) fn with_dangling_comments( + self, + comments: &'content [SourceComment], + ) -> FormatParenthesized<'content, 'ast> { + FormatParenthesized { comments, ..self } + } +} + impl<'ast> Format> for FormatParenthesized<'_, 'ast> { fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { let inner = format_with(|f| { group(&format_args![ text(self.left), - &soft_block_indent(&Arguments::from(&self.content)), + dangling_open_parenthesis_comments(self.comments), + soft_block_indent(&Arguments::from(&self.content)), text(self.right) ]) .fmt(f) @@ -170,8 +214,8 @@ pub(crate) struct FormatOptionalParentheses<'content, 'ast> { impl<'ast> Format> for FormatOptionalParentheses<'_, 'ast> { fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - // The group id is used as a condition in [`in_parentheses_only`] to create a conditional group - // that is only active if the optional parentheses group expands. + // The group id is used as a condition in [`in_parentheses_only_group`] to create a + // conditional group that is only active if the optional parentheses group expands. let parens_id = f.group_id("optional_parentheses"); let mut f = WithNodeLevel::new(NodeLevel::Expression(Some(parens_id)), f); @@ -240,7 +284,8 @@ impl<'ast> Format> for InParenthesesOnlyLineBreak { f.write_element(FormatElement::Line(match self { InParenthesesOnlyLineBreak::SoftLineBreak => LineMode::Soft, InParenthesesOnlyLineBreak::SoftLineBreakOrSpace => LineMode::SoftOrSpace, - })) + })); + Ok(()) } } } @@ -285,3 +330,82 @@ impl<'ast> Format> for FormatInParenthesesOnlyGroup<'_, 'a } } } + +/// Format comments inside empty parentheses, brackets or curly braces. +/// +/// Empty `()`, `[]` and `{}` are special because there can be dangling comments, and they can be in +/// two positions: +/// ```python +/// x = [ # end-of-line +/// # own line +/// ] +/// ``` +/// These comments are dangling because they can't be assigned to any element inside as they would +/// in all other cases. +pub(crate) fn empty_parenthesized<'content>( + left: &'static str, + comments: &'content [SourceComment], + right: &'static str, +) -> FormatEmptyParenthesized<'content> { + FormatEmptyParenthesized { + left, + comments, + right, + } +} + +pub(crate) struct FormatEmptyParenthesized<'content> { + left: &'static str, + comments: &'content [SourceComment], + right: &'static str, +} + +impl Format> for FormatEmptyParenthesized<'_> { + fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { + let end_of_line_split = self + .comments + .partition_point(|comment| comment.line_position().is_end_of_line()); + debug_assert!(self.comments[end_of_line_split..] + .iter() + .all(|comment| comment.line_position().is_own_line())); + write!( + f, + [group(&format_args![ + text(self.left), + // end-of-line comments + trailing_comments(&self.comments[..end_of_line_split]), + // Avoid unstable formatting with + // ```python + // x = () - (# + // ) + // ``` + // Without this the comment would go after the empty tuple first, but still expand + // the bin op. In the second formatting pass they are trailing bin op comments + // so the bin op collapse. Suboptimally we keep parentheses around the bin op in + // either case. + (!self.comments[..end_of_line_split].is_empty()).then_some(hard_line_break()), + // own line comments, which need to be indented + soft_block_indent(&dangling_comments(&self.comments[end_of_line_split..])), + text(self.right) + ])] + ) + } +} + +#[cfg(test)] +mod tests { + use ruff_python_ast::ExpressionRef; + use ruff_python_parser::parse_expression; + + use crate::expression::parentheses::is_expression_parenthesized; + + #[test] + fn test_has_parentheses() { + let expression = r#"(b().c("")).d()"#; + let expr = parse_expression(expression, "").unwrap(); + assert!(!is_expression_parenthesized( + ExpressionRef::from(&expr), + expression + )); + } +} diff --git a/crates/ruff_python_formatter/src/expression/string.rs b/crates/ruff_python_formatter/src/expression/string.rs index b315b8c1a1eeb..8762fc69ce846 100644 --- a/crates/ruff_python_formatter/src/expression/string.rs +++ b/crates/ruff_python_formatter/src/expression/string.rs @@ -1,16 +1,15 @@ use std::borrow::Cow; use bitflags::bitflags; + +use ruff_formatter::{format_args, write, FormatError}; use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::{self as ast, ExprConstant, ExprJoinedStr, Ranged}; +use ruff_python_ast::{self as ast, ExprConstant, ExprFString, Ranged}; use ruff_python_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType}; use ruff_python_parser::{Mode, Tok}; use ruff_source_file::Locator; use ruff_text_size::{TextLen, TextRange, TextSize}; -use ruff_formatter::{format_args, write, FormatError}; -use ruff_python_ast::str::is_implicit_concatenation; - use crate::comments::{leading_comments, trailing_comments}; use crate::expression::parentheses::{ in_parentheses_only_group, in_parentheses_only_soft_line_break_or_space, @@ -27,15 +26,15 @@ enum Quoting { pub(super) enum AnyString<'a> { Constant(&'a ExprConstant), - JoinedStr(&'a ExprJoinedStr), + FString(&'a ExprFString), } impl<'a> AnyString<'a> { fn quoting(&self, locator: &Locator) -> Quoting { match self { Self::Constant(_) => Quoting::CanChange, - Self::JoinedStr(joined_str) => { - if joined_str.values.iter().any(|value| match value { + Self::FString(f_string) => { + if f_string.values.iter().any(|value| match value { Expr::FormattedValue(ast::ExprFormattedValue { range, .. }) => { let string_content = locator.slice(*range); string_content.contains(['"', '\'']) @@ -49,13 +48,24 @@ impl<'a> AnyString<'a> { } } } + + /// Returns `true` if the string is implicitly concatenated. + fn implicit_concatenated(&self) -> bool { + match self { + Self::Constant(ExprConstant { value, .. }) => value.is_implicit_concatenated(), + Self::FString(ExprFString { + implicit_concatenated, + .. + }) => *implicit_concatenated, + } + } } impl Ranged for AnyString<'_> { fn range(&self) -> TextRange { match self { Self::Constant(expr) => expr.range(), - Self::JoinedStr(expr) => expr.range(), + Self::FString(expr) => expr.range(), } } } @@ -64,7 +74,7 @@ impl<'a> From<&AnyString<'a>> for AnyNodeRef<'a> { fn from(value: &AnyString<'a>) -> Self { match value { AnyString::Constant(expr) => AnyNodeRef::ExprConstant(expr), - AnyString::JoinedStr(expr) => AnyNodeRef::ExprJoinedStr(expr), + AnyString::FString(expr) => AnyNodeRef::ExprFString(expr), } } } @@ -78,7 +88,7 @@ pub(super) struct FormatString<'a> { pub enum StringLayout { #[default] Default, - + DocString, ImplicitConcatenatedBinaryLeftSide, } @@ -100,19 +110,31 @@ impl<'a> FormatString<'a> { } impl<'a> Format> for FormatString<'a> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { match self.layout { StringLayout::Default => { - let string_range = self.string.range(); - let string_content = f.context().locator().slice(string_range); - - if is_implicit_concatenation(string_content) { + if self.string.implicit_concatenated() { in_parentheses_only_group(&FormatStringContinuation::new(self.string)).fmt(f) } else { - FormatStringPart::new(string_range, self.string.quoting(&f.context().locator())) - .fmt(f) + FormatStringPart::new( + self.string.range(), + self.string.quoting(&f.context().locator()), + &f.context().locator(), + f.options().quote_style(), + ) + .fmt(f) } } + StringLayout::DocString => { + let string_part = FormatStringPart::new( + self.string.range(), + // f-strings can't be docstrings + Quoting::CanChange, + &f.context().locator(), + f.options().quote_style(), + ); + format_docstring(&string_part, f) + } StringLayout::ImplicitConcatenatedBinaryLeftSide => { FormatStringContinuation::new(self.string).fmt(f) } @@ -134,10 +156,11 @@ impl<'a> FormatStringContinuation<'a> { } impl Format> for FormatStringContinuation<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let comments = f.context().comments().clone(); let locator = f.context().locator(); - let mut dangling_comments = comments.dangling_comments(self.string); + let quote_style = f.options().quote_style(); + let mut dangling_comments = comments.dangling(self.string); let string_range = self.string.range(); let string_content = locator.slice(string_range); @@ -213,7 +236,12 @@ impl Format> for FormatStringContinuation<'_> { joiner.entry(&format_args![ line_suffix_boundary(), leading_comments(leading_part_comments), - FormatStringPart::new(token_range, self.string.quoting(&locator)), + FormatStringPart::new( + token_range, + self.string.quoting(&locator), + &locator, + quote_style, + ), trailing_comments(trailing_part_comments) ]); @@ -235,63 +263,73 @@ impl Format> for FormatStringContinuation<'_> { } struct FormatStringPart { - part_range: TextRange, - quoting: Quoting, + prefix: StringPrefix, + preferred_quotes: StringQuotes, + range: TextRange, + is_raw_string: bool, } -impl FormatStringPart { - const fn new(range: TextRange, quoting: Quoting) -> Self { - Self { - part_range: range, - quoting, - } +impl Ranged for FormatStringPart { + fn range(&self) -> TextRange { + self.range } } -impl Format> for FormatStringPart { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - let string_content = f.context().locator().slice(self.part_range); +impl FormatStringPart { + fn new(range: TextRange, quoting: Quoting, locator: &Locator, quote_style: QuoteStyle) -> Self { + let string_content = locator.slice(range); let prefix = StringPrefix::parse(string_content); let after_prefix = &string_content[usize::from(prefix.text_len())..]; - let quotes = StringQuotes::parse(after_prefix).ok_or(FormatError::syntax_error( - "Didn't find string quotes after prefix", - ))?; + let quotes = + StringQuotes::parse(after_prefix).expect("Didn't find string quotes after prefix"); let relative_raw_content_range = TextRange::new( prefix.text_len() + quotes.text_len(), string_content.text_len() - quotes.text_len(), ); - let raw_content_range = relative_raw_content_range + self.part_range.start(); + let raw_content_range = relative_raw_content_range + range.start(); let raw_content = &string_content[relative_raw_content_range]; let is_raw_string = prefix.is_raw_string(); - let preferred_quotes = match self.quoting { + let preferred_quotes = match quoting { Quoting::Preserve => quotes, Quoting::CanChange => { if is_raw_string { - preferred_quotes_raw(raw_content, quotes, f.options().quote_style()) + preferred_quotes_raw(raw_content, quotes, quote_style) } else { - preferred_quotes(raw_content, quotes, f.options().quote_style()) + preferred_quotes(raw_content, quotes, quote_style) } } }; - write!(f, [prefix, preferred_quotes])?; + Self { + prefix, + range: raw_content_range, + preferred_quotes, + is_raw_string, + } + } +} - let (normalized, contains_newlines) = - normalize_string(raw_content, preferred_quotes, is_raw_string); +impl Format> for FormatStringPart { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + let (normalized, contains_newlines) = normalize_string( + f.context().locator().slice(self.range), + self.preferred_quotes, + self.is_raw_string, + ); + write!(f, [self.prefix, self.preferred_quotes])?; match normalized { Cow::Borrowed(_) => { - source_text_slice(raw_content_range, contains_newlines).fmt(f)?; + source_text_slice(self.range(), contains_newlines).fmt(f)?; } Cow::Owned(normalized) => { - dynamic_text(&normalized, Some(raw_content_range.start())).fmt(f)?; + dynamic_text(&normalized, Some(self.start())).fmt(f)?; } } - - preferred_quotes.fmt(f) + self.preferred_quotes.fmt(f) } } @@ -339,12 +377,12 @@ impl StringPrefix { } pub(super) const fn is_raw_string(self) -> bool { - matches!(self, StringPrefix::RAW | StringPrefix::RAW_UPPER) + self.contains(StringPrefix::RAW) || self.contains(StringPrefix::RAW_UPPER) } } impl Format> for StringPrefix { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { // Retain the casing for the raw prefix: // https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings if self.contains(StringPrefix::RAW) { @@ -550,7 +588,7 @@ impl StringQuotes { } impl Format> for StringQuotes { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { let quotes = match (self.style, self.triple) { (QuoteStyle::Single, false) => "'", (QuoteStyle::Single, true) => "'''", @@ -639,3 +677,311 @@ fn normalize_string( (normalized, newlines) } + +/// For docstring indentation, black counts spaces as 1 and tabs by increasing the indentation up +/// to the next multiple of 8. This is effectively a port of +/// [`str.expandtabs`](https://docs.python.org/3/library/stdtypes.html#str.expandtabs), +/// which black [calls with the default tab width of 8](https://github.com/psf/black/blob/c36e468794f9256d5e922c399240d49782ba04f1/src/black/strings.py#L61) +fn count_indentation_like_black(line: &str) -> TextSize { + let tab_width: u32 = 8; + let mut indentation = TextSize::default(); + for char in line.chars() { + if char == '\t' { + // Pad to the next multiple of tab_width + indentation += TextSize::from(tab_width - (indentation.to_u32().rem_euclid(tab_width))); + } else if char.is_whitespace() { + indentation += char.text_len(); + } else { + return indentation; + } + } + indentation +} + +/// Format a docstring by trimming whitespace and adjusting the indentation. +/// +/// Summary of changes we make: +/// * Normalize the string like all other strings +/// * Ignore docstring that have an escaped newline +/// * Trim all trailing whitespace, except for a chaperone space that avoids quotes or backslashes +/// in the last line. +/// * Trim leading whitespace on the first line, again except for a chaperone space +/// * If there is only content in the first line and after that only whitespace, collapse the +/// docstring into one line +/// * Adjust the indentation (see below) +/// +/// # Docstring indentation +/// +/// Unlike any other string, like black we change the indentation of docstring lines. +/// +/// We want to preserve the indentation inside the docstring relative to the suite statement/block +/// indent that the docstring statement is in, but also want to apply the change of the outer +/// indentation in the docstring, e.g. +/// ```python +/// def sparkle_sky(): +/// """Make a pretty sparkly sky. +/// * * ✨ *. . +/// * * ✨ . +/// . * . ✨ * . . +/// """ +/// ``` +/// should become +/// ```python +/// def sparkle_sky(): +/// """Make a pretty sparkly sky. +/// * * ✨ *. . +/// * * ✨ . +/// . * . ✨ * . . +/// """ +/// ``` +/// We can't compute the full indentation here since we don't know what the block indent of +/// the doc comment will be yet and which we can only have added by formatting each line +/// separately with a hard line break. This means we need to strip shared indentation from +/// docstring while preserving the in-docstring bigger-than-suite-statement indentation. Example: +/// ```python +/// def f(): +/// """first line +/// line a +/// line b +/// """ +/// ``` +/// The docstring indentation is 2, the block indents will change this to 4 (but we can't +/// determine this at this point). The indentation of line a is 2, so we trim ` line a` +/// to `line a`. For line b it's 5, so we trim it to `line b` and pad with 5-2=3 spaces to +/// ` line b`. The closing quotes, being on their own line, are stripped get only the +/// default indentation. Fully formatted: +/// ```python +/// def f(): +/// """first line +/// line a +/// line b +/// """ +/// ``` +/// +/// Tabs are counted by padding them to the next multiple of 8 according to +/// [`str.expandtabs`](https://docs.python.org/3/library/stdtypes.html#str.expandtabs). When +/// we see indentation that contains a tab or any other none ascii-space whitespace we rewrite the +/// string. +/// +/// Additionally, if any line in the docstring has less indentation than the docstring +/// (effectively a negative indentation wrt. to the current level), we pad all lines to the +/// level of the docstring with spaces. +/// ```python +/// def f(): +/// """first line +/// line a +/// line b +/// line c +/// """ +/// ``` +/// Here line a is 3 columns negatively indented, so we pad all lines by an extra 3 spaces: +/// ```python +/// def f(): +/// """first line +/// line a +/// line b +/// line c +/// """ +/// ``` +fn format_docstring(string_part: &FormatStringPart, f: &mut PyFormatter) -> FormatResult<()> { + let locator = f.context().locator(); + + // Black doesn't change the indentation of docstrings that contain an escaped newline + if locator.slice(string_part.range()).contains("\\\n") { + return string_part.fmt(f); + } + + let (normalized, _) = normalize_string( + locator.slice(string_part.range()), + string_part.preferred_quotes, + string_part.is_raw_string, + ); + // is_borrowed is unstable :/ + let already_normalized = matches!(normalized, Cow::Borrowed(_)); + + let mut lines = normalized.lines().peekable(); + + // Start the string + write!( + f, + [ + source_position(string_part.start()), + string_part.prefix, + string_part.preferred_quotes + ] + )?; + // We track where in the source docstring we are (in source code byte offsets) + let mut offset = string_part.start(); + + // The first line directly after the opening quotes has different rules than the rest, mainly + // that we remove all leading whitespace as there's no indentation + let first = lines.next().unwrap_or_default(); + // Black trims whitespace using [`str.strip()`](https://docs.python.org/3/library/stdtypes.html#str.strip) + // https://github.com/psf/black/blob/b4dca26c7d93f930bbd5a7b552807370b60d4298/src/black/strings.py#L77-L85 + // So we use the unicode whitespace definition through `trim_{start,end}` instead of the python + // tokenizer whitespace definition in `trim_whitespace_{start,end}`. + let trim_end = first.trim_end(); + let trim_both = trim_end.trim_start(); + + // Edge case: The first line is `""" "content`, so we need to insert chaperone space that keep + // inner quotes and closing quotes from getting to close to avoid `""""content` + if trim_both.starts_with(string_part.preferred_quotes.style.as_char()) { + space().fmt(f)?; + } + + if !trim_end.is_empty() { + // For the first line of the docstring we strip the leading and trailing whitespace, e.g. + // `""" content ` to `"""content` + let leading_whitespace = trim_end.text_len() - trim_both.text_len(); + let trimmed_line_range = + TextRange::at(offset, trim_end.text_len()).add_start(leading_whitespace); + if already_normalized { + source_text_slice(trimmed_line_range, ContainsNewlines::No).fmt(f)?; + } else { + dynamic_text(trim_both, Some(trimmed_line_range.start())).fmt(f)?; + } + } + offset += first.text_len(); + + // Check if we have a single line (or empty) docstring + if normalized[first.len()..].trim().is_empty() { + // For `"""\n"""` or other whitespace between the quotes, black keeps a single whitespace, + // but `""""""` doesn't get one inserted. + if needs_chaperone_space(string_part, trim_end) + || (trim_end.is_empty() && !normalized.is_empty()) + { + space().fmt(f)?; + } + string_part.preferred_quotes.fmt(f)?; + return Ok(()); + } + + hard_line_break().fmt(f)?; + // We know that the normalized string has \n line endings + offset += "\n".text_len(); + + // If some line of the docstring is less indented than the function body, we pad all lines to + // align it with the docstring statement. Conversely, if all lines are over-indented, we strip + // the extra indentation. We call this stripped indentation since it's relative to the block + // indent printer-made indentation. + let stripped_indentation = lines + .clone() + // We don't want to count whitespace-only lines as miss-indented + .filter(|line| !line.trim().is_empty()) + .map(count_indentation_like_black) + .min() + .unwrap_or_default(); + + while let Some(line) = lines.next() { + let is_last = lines.peek().is_none(); + format_docstring_line( + line, + is_last, + offset, + stripped_indentation, + already_normalized, + f, + )?; + // We know that the normalized string has \n line endings + offset += line.text_len() + "\n".text_len(); + } + + // Same special case in the last line as for the first line + let trim_end = normalized + .as_ref() + .trim_end_matches(|c: char| c.is_whitespace() && c != '\n'); + if needs_chaperone_space(string_part, trim_end) { + space().fmt(f)?; + } + + write!( + f, + [ + string_part.preferred_quotes, + source_position(string_part.end()) + ] + ) +} + +/// If the last line of the docstring is `content" """` or `content\ """`, we need a chaperone space +/// that avoids `content""""` and `content\"""`. This does only applies to un-escaped backslashes, +/// so `content\\ """` doesn't need a space while `content\\\ """` does. +fn needs_chaperone_space(string_part: &FormatStringPart, trim_end: &str) -> bool { + trim_end.ends_with(string_part.preferred_quotes.style.as_char()) + || trim_end.chars().rev().take_while(|c| *c == '\\').count() % 2 == 1 +} + +/// Format a docstring line that is not the first line +fn format_docstring_line( + line: &str, + is_last: bool, + offset: TextSize, + stripped_indentation: TextSize, + already_normalized: bool, + f: &mut PyFormatter, +) -> FormatResult<()> { + let trim_end = line.trim_end(); + if trim_end.is_empty() { + return if is_last { + // If the doc string ends with ` """`, the last line is ` `, but we don't want to + // insert an empty line (but close the docstring) + Ok(()) + } else { + empty_line().fmt(f) + }; + } + + let tab_or_non_ascii_space = trim_end + .chars() + .take_while(|c| c.is_whitespace()) + .any(|c| c != ' '); + + if tab_or_non_ascii_space { + // We strip the indentation that is shared with the docstring statement, unless a line + // was indented less than the docstring statement, in which we strip only this much + // indentation to implicitly pad all lines by the difference, or all lines were + // overindented, in which case we strip the additional whitespace (see example in + // [`format_docstring`] doc comment). We then prepend the in-docstring indentation to the + // string. + let indent_len = count_indentation_like_black(trim_end) - stripped_indentation; + let in_docstring_indent = " ".repeat(indent_len.to_usize()) + trim_end.trim_start(); + dynamic_text(&in_docstring_indent, Some(offset)).fmt(f)?; + } else { + // Take the string with the trailing whitespace removed, then also skip the leading + // whitespace + let trimmed_line_range = + TextRange::at(offset, trim_end.text_len()).add_start(stripped_indentation); + if already_normalized { + source_text_slice(trimmed_line_range, ContainsNewlines::No).fmt(f)?; + } else { + // All indents are ascii spaces, so the slicing is correct + dynamic_text( + &trim_end[stripped_indentation.to_usize()..], + Some(trimmed_line_range.start()), + ) + .fmt(f)?; + } + } + + // We handled the case that the closing quotes are on their own line above (the last line is + // empty except for whitespace). If they are on the same line as content, we don't insert a line + // break. + if !is_last { + hard_line_break().fmt(f)?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use crate::expression::string::count_indentation_like_black; + + #[test] + fn test_indentation_like_black() { + assert_eq!(count_indentation_like_black("\t \t \t").to_u32(), 24); + assert_eq!(count_indentation_like_black("\t \t").to_u32(), 24); + assert_eq!(count_indentation_like_black("\t\t\t").to_u32(), 24); + assert_eq!(count_indentation_like_black(" ").to_u32(), 4); + } +} diff --git a/crates/ruff_python_formatter/src/generated.rs b/crates/ruff_python_formatter/src/generated.rs index b3c25081792ac..5541df5c4bd21 100644 --- a/crates/ruff_python_formatter/src/generated.rs +++ b/crates/ruff_python_formatter/src/generated.rs @@ -2,8 +2,7 @@ #![allow(unknown_lints, clippy::default_constructed_unit_structs)] use crate::context::PyFormatContext; -use crate::{AsFormat, FormatNodeRule, IntoFormat}; -use ruff_formatter::formatter::Formatter; +use crate::{AsFormat, FormatNodeRule, IntoFormat, PyFormatter}; use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule, FormatResult, FormatRule}; use ruff_python_ast as ast; @@ -11,11 +10,7 @@ impl FormatRule> for crate::module::mod_module::FormatModModule { #[inline] - fn fmt( - &self, - node: &ast::ModModule, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ModModule, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -45,11 +40,7 @@ impl FormatRule> for crate::module::mod_expression::FormatModExpression { #[inline] - fn fmt( - &self, - node: &ast::ModExpression, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ModExpression, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -85,11 +76,7 @@ impl FormatRule> for crate::statement::stmt_function_def::FormatStmtFunctionDef { #[inline] - fn fmt( - &self, - node: &ast::StmtFunctionDef, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtFunctionDef, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -121,55 +108,11 @@ impl<'ast> IntoFormat> for ast::StmtFunctionDef { } } -impl FormatRule> - for crate::statement::stmt_async_function_def::FormatStmtAsyncFunctionDef -{ - #[inline] - fn fmt( - &self, - node: &ast::StmtAsyncFunctionDef, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) - } -} -impl<'ast> AsFormat> for ast::StmtAsyncFunctionDef { - type Format<'a> = FormatRefWithRule< - 'a, - ast::StmtAsyncFunctionDef, - crate::statement::stmt_async_function_def::FormatStmtAsyncFunctionDef, - PyFormatContext<'ast>, - >; - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new( - self, - crate::statement::stmt_async_function_def::FormatStmtAsyncFunctionDef::default(), - ) - } -} -impl<'ast> IntoFormat> for ast::StmtAsyncFunctionDef { - type Format = FormatOwnedWithRule< - ast::StmtAsyncFunctionDef, - crate::statement::stmt_async_function_def::FormatStmtAsyncFunctionDef, - PyFormatContext<'ast>, - >; - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new( - self, - crate::statement::stmt_async_function_def::FormatStmtAsyncFunctionDef::default(), - ) - } -} - impl FormatRule> for crate::statement::stmt_class_def::FormatStmtClassDef { #[inline] - fn fmt( - &self, - node: &ast::StmtClassDef, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtClassDef, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -205,11 +148,7 @@ impl FormatRule> for crate::statement::stmt_return::FormatStmtReturn { #[inline] - fn fmt( - &self, - node: &ast::StmtReturn, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtReturn, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -245,11 +184,7 @@ impl FormatRule> for crate::statement::stmt_delete::FormatStmtDelete { #[inline] - fn fmt( - &self, - node: &ast::StmtDelete, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtDelete, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -285,11 +220,7 @@ impl FormatRule> for crate::statement::stmt_type_alias::FormatStmtTypeAlias { #[inline] - fn fmt( - &self, - node: &ast::StmtTypeAlias, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtTypeAlias, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -325,11 +256,7 @@ impl FormatRule> for crate::statement::stmt_assign::FormatStmtAssign { #[inline] - fn fmt( - &self, - node: &ast::StmtAssign, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtAssign, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -365,11 +292,7 @@ impl FormatRule> for crate::statement::stmt_aug_assign::FormatStmtAugAssign { #[inline] - fn fmt( - &self, - node: &ast::StmtAugAssign, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtAugAssign, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -405,11 +328,7 @@ impl FormatRule> for crate::statement::stmt_ann_assign::FormatStmtAnnAssign { #[inline] - fn fmt( - &self, - node: &ast::StmtAnnAssign, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtAnnAssign, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -443,7 +362,7 @@ impl<'ast> IntoFormat> for ast::StmtAnnAssign { impl FormatRule> for crate::statement::stmt_for::FormatStmtFor { #[inline] - fn fmt(&self, node: &ast::StmtFor, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtFor, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -469,55 +388,11 @@ impl<'ast> IntoFormat> for ast::StmtFor { } } -impl FormatRule> - for crate::statement::stmt_async_for::FormatStmtAsyncFor -{ - #[inline] - fn fmt( - &self, - node: &ast::StmtAsyncFor, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) - } -} -impl<'ast> AsFormat> for ast::StmtAsyncFor { - type Format<'a> = FormatRefWithRule< - 'a, - ast::StmtAsyncFor, - crate::statement::stmt_async_for::FormatStmtAsyncFor, - PyFormatContext<'ast>, - >; - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new( - self, - crate::statement::stmt_async_for::FormatStmtAsyncFor::default(), - ) - } -} -impl<'ast> IntoFormat> for ast::StmtAsyncFor { - type Format = FormatOwnedWithRule< - ast::StmtAsyncFor, - crate::statement::stmt_async_for::FormatStmtAsyncFor, - PyFormatContext<'ast>, - >; - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new( - self, - crate::statement::stmt_async_for::FormatStmtAsyncFor::default(), - ) - } -} - impl FormatRule> for crate::statement::stmt_while::FormatStmtWhile { #[inline] - fn fmt( - &self, - node: &ast::StmtWhile, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtWhile, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -551,7 +426,7 @@ impl<'ast> IntoFormat> for ast::StmtWhile { impl FormatRule> for crate::statement::stmt_if::FormatStmtIf { #[inline] - fn fmt(&self, node: &ast::StmtIf, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtIf, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -581,11 +456,7 @@ impl FormatRule> for crate::statement::stmt_with::FormatStmtWith { #[inline] - fn fmt( - &self, - node: &ast::StmtWith, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtWith, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -611,55 +482,11 @@ impl<'ast> IntoFormat> for ast::StmtWith { } } -impl FormatRule> - for crate::statement::stmt_async_with::FormatStmtAsyncWith -{ - #[inline] - fn fmt( - &self, - node: &ast::StmtAsyncWith, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) - } -} -impl<'ast> AsFormat> for ast::StmtAsyncWith { - type Format<'a> = FormatRefWithRule< - 'a, - ast::StmtAsyncWith, - crate::statement::stmt_async_with::FormatStmtAsyncWith, - PyFormatContext<'ast>, - >; - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new( - self, - crate::statement::stmt_async_with::FormatStmtAsyncWith::default(), - ) - } -} -impl<'ast> IntoFormat> for ast::StmtAsyncWith { - type Format = FormatOwnedWithRule< - ast::StmtAsyncWith, - crate::statement::stmt_async_with::FormatStmtAsyncWith, - PyFormatContext<'ast>, - >; - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new( - self, - crate::statement::stmt_async_with::FormatStmtAsyncWith::default(), - ) - } -} - impl FormatRule> for crate::statement::stmt_match::FormatStmtMatch { #[inline] - fn fmt( - &self, - node: &ast::StmtMatch, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtMatch, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -695,11 +522,7 @@ impl FormatRule> for crate::statement::stmt_raise::FormatStmtRaise { #[inline] - fn fmt( - &self, - node: &ast::StmtRaise, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtRaise, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -733,7 +556,7 @@ impl<'ast> IntoFormat> for ast::StmtRaise { impl FormatRule> for crate::statement::stmt_try::FormatStmtTry { #[inline] - fn fmt(&self, node: &ast::StmtTry, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtTry, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -759,55 +582,11 @@ impl<'ast> IntoFormat> for ast::StmtTry { } } -impl FormatRule> - for crate::statement::stmt_try_star::FormatStmtTryStar -{ - #[inline] - fn fmt( - &self, - node: &ast::StmtTryStar, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) - } -} -impl<'ast> AsFormat> for ast::StmtTryStar { - type Format<'a> = FormatRefWithRule< - 'a, - ast::StmtTryStar, - crate::statement::stmt_try_star::FormatStmtTryStar, - PyFormatContext<'ast>, - >; - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new( - self, - crate::statement::stmt_try_star::FormatStmtTryStar::default(), - ) - } -} -impl<'ast> IntoFormat> for ast::StmtTryStar { - type Format = FormatOwnedWithRule< - ast::StmtTryStar, - crate::statement::stmt_try_star::FormatStmtTryStar, - PyFormatContext<'ast>, - >; - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new( - self, - crate::statement::stmt_try_star::FormatStmtTryStar::default(), - ) - } -} - impl FormatRule> for crate::statement::stmt_assert::FormatStmtAssert { #[inline] - fn fmt( - &self, - node: &ast::StmtAssert, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtAssert, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -843,11 +622,7 @@ impl FormatRule> for crate::statement::stmt_import::FormatStmtImport { #[inline] - fn fmt( - &self, - node: &ast::StmtImport, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtImport, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -883,11 +658,7 @@ impl FormatRule> for crate::statement::stmt_import_from::FormatStmtImportFrom { #[inline] - fn fmt( - &self, - node: &ast::StmtImportFrom, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtImportFrom, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -923,11 +694,7 @@ impl FormatRule> for crate::statement::stmt_global::FormatStmtGlobal { #[inline] - fn fmt( - &self, - node: &ast::StmtGlobal, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtGlobal, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -963,11 +730,7 @@ impl FormatRule> for crate::statement::stmt_nonlocal::FormatStmtNonlocal { #[inline] - fn fmt( - &self, - node: &ast::StmtNonlocal, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtNonlocal, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1003,11 +766,7 @@ impl FormatRule> for crate::statement::stmt_expr::FormatStmtExpr { #[inline] - fn fmt( - &self, - node: &ast::StmtExpr, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtExpr, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1037,11 +796,7 @@ impl FormatRule> for crate::statement::stmt_pass::FormatStmtPass { #[inline] - fn fmt( - &self, - node: &ast::StmtPass, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtPass, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1071,11 +826,7 @@ impl FormatRule> for crate::statement::stmt_break::FormatStmtBreak { #[inline] - fn fmt( - &self, - node: &ast::StmtBreak, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtBreak, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1111,11 +862,7 @@ impl FormatRule> for crate::statement::stmt_continue::FormatStmtContinue { #[inline] - fn fmt( - &self, - node: &ast::StmtContinue, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::StmtContinue, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1147,15 +894,47 @@ impl<'ast> IntoFormat> for ast::StmtContinue { } } +impl FormatRule> + for crate::statement::stmt_ipy_escape_command::FormatStmtIpyEscapeCommand +{ + #[inline] + fn fmt(&self, node: &ast::StmtIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::StmtIpyEscapeCommand { + type Format<'a> = FormatRefWithRule< + 'a, + ast::StmtIpyEscapeCommand, + crate::statement::stmt_ipy_escape_command::FormatStmtIpyEscapeCommand, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::statement::stmt_ipy_escape_command::FormatStmtIpyEscapeCommand::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::StmtIpyEscapeCommand { + type Format = FormatOwnedWithRule< + ast::StmtIpyEscapeCommand, + crate::statement::stmt_ipy_escape_command::FormatStmtIpyEscapeCommand, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::statement::stmt_ipy_escape_command::FormatStmtIpyEscapeCommand::default(), + ) + } +} + impl FormatRule> for crate::expression::expr_bool_op::FormatExprBoolOp { #[inline] - fn fmt( - &self, - node: &ast::ExprBoolOp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprBoolOp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1191,11 +970,7 @@ impl FormatRule> for crate::expression::expr_named_expr::FormatExprNamedExpr { #[inline] - fn fmt( - &self, - node: &ast::ExprNamedExpr, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprNamedExpr, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1231,11 +1006,7 @@ impl FormatRule> for crate::expression::expr_bin_op::FormatExprBinOp { #[inline] - fn fmt( - &self, - node: &ast::ExprBinOp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprBinOp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1271,11 +1042,7 @@ impl FormatRule> for crate::expression::expr_unary_op::FormatExprUnaryOp { #[inline] - fn fmt( - &self, - node: &ast::ExprUnaryOp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprUnaryOp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1311,11 +1078,7 @@ impl FormatRule> for crate::expression::expr_lambda::FormatExprLambda { #[inline] - fn fmt( - &self, - node: &ast::ExprLambda, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprLambda, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1351,11 +1114,7 @@ impl FormatRule> for crate::expression::expr_if_exp::FormatExprIfExp { #[inline] - fn fmt( - &self, - node: &ast::ExprIfExp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprIfExp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1391,11 +1150,7 @@ impl FormatRule> for crate::expression::expr_dict::FormatExprDict { #[inline] - fn fmt( - &self, - node: &ast::ExprDict, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprDict, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1429,7 +1184,7 @@ impl<'ast> IntoFormat> for ast::ExprDict { impl FormatRule> for crate::expression::expr_set::FormatExprSet { #[inline] - fn fmt(&self, node: &ast::ExprSet, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprSet, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1459,11 +1214,7 @@ impl FormatRule> for crate::expression::expr_list_comp::FormatExprListComp { #[inline] - fn fmt( - &self, - node: &ast::ExprListComp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprListComp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1499,11 +1250,7 @@ impl FormatRule> for crate::expression::expr_set_comp::FormatExprSetComp { #[inline] - fn fmt( - &self, - node: &ast::ExprSetComp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprSetComp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1539,11 +1286,7 @@ impl FormatRule> for crate::expression::expr_dict_comp::FormatExprDictComp { #[inline] - fn fmt( - &self, - node: &ast::ExprDictComp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprDictComp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1579,11 +1322,7 @@ impl FormatRule> for crate::expression::expr_generator_exp::FormatExprGeneratorExp { #[inline] - fn fmt( - &self, - node: &ast::ExprGeneratorExp, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprGeneratorExp, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1619,11 +1358,7 @@ impl FormatRule> for crate::expression::expr_await::FormatExprAwait { #[inline] - fn fmt( - &self, - node: &ast::ExprAwait, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprAwait, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1659,11 +1394,7 @@ impl FormatRule> for crate::expression::expr_yield::FormatExprYield { #[inline] - fn fmt( - &self, - node: &ast::ExprYield, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprYield, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1699,11 +1430,7 @@ impl FormatRule> for crate::expression::expr_yield_from::FormatExprYieldFrom { #[inline] - fn fmt( - &self, - node: &ast::ExprYieldFrom, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprYieldFrom, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1739,11 +1466,7 @@ impl FormatRule> for crate::expression::expr_compare::FormatExprCompare { #[inline] - fn fmt( - &self, - node: &ast::ExprCompare, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprCompare, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1779,11 +1502,7 @@ impl FormatRule> for crate::expression::expr_call::FormatExprCall { #[inline] - fn fmt( - &self, - node: &ast::ExprCall, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprCall, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1819,11 +1538,7 @@ impl FormatRule> for crate::expression::expr_formatted_value::FormatExprFormattedValue { #[inline] - fn fmt( - &self, - node: &ast::ExprFormattedValue, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprFormattedValue, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1855,42 +1570,38 @@ impl<'ast> IntoFormat> for ast::ExprFormattedValue { } } -impl FormatRule> - for crate::expression::expr_joined_str::FormatExprJoinedStr +impl FormatRule> + for crate::expression::expr_f_string::FormatExprFString { #[inline] - fn fmt( - &self, - node: &ast::ExprJoinedStr, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) + fn fmt(&self, node: &ast::ExprFString, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) } } -impl<'ast> AsFormat> for ast::ExprJoinedStr { +impl<'ast> AsFormat> for ast::ExprFString { type Format<'a> = FormatRefWithRule< 'a, - ast::ExprJoinedStr, - crate::expression::expr_joined_str::FormatExprJoinedStr, + ast::ExprFString, + crate::expression::expr_f_string::FormatExprFString, PyFormatContext<'ast>, >; fn format(&self) -> Self::Format<'_> { FormatRefWithRule::new( self, - crate::expression::expr_joined_str::FormatExprJoinedStr::default(), + crate::expression::expr_f_string::FormatExprFString::default(), ) } } -impl<'ast> IntoFormat> for ast::ExprJoinedStr { +impl<'ast> IntoFormat> for ast::ExprFString { type Format = FormatOwnedWithRule< - ast::ExprJoinedStr, - crate::expression::expr_joined_str::FormatExprJoinedStr, + ast::ExprFString, + crate::expression::expr_f_string::FormatExprFString, PyFormatContext<'ast>, >; fn into_format(self) -> Self::Format { FormatOwnedWithRule::new( self, - crate::expression::expr_joined_str::FormatExprJoinedStr::default(), + crate::expression::expr_f_string::FormatExprFString::default(), ) } } @@ -1899,11 +1610,7 @@ impl FormatRule> for crate::expression::expr_constant::FormatExprConstant { #[inline] - fn fmt( - &self, - node: &ast::ExprConstant, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprConstant, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1939,11 +1646,7 @@ impl FormatRule> for crate::expression::expr_attribute::FormatExprAttribute { #[inline] - fn fmt( - &self, - node: &ast::ExprAttribute, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprAttribute, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -1979,11 +1682,7 @@ impl FormatRule> for crate::expression::expr_subscript::FormatExprSubscript { #[inline] - fn fmt( - &self, - node: &ast::ExprSubscript, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprSubscript, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2019,11 +1718,7 @@ impl FormatRule> for crate::expression::expr_starred::FormatExprStarred { #[inline] - fn fmt( - &self, - node: &ast::ExprStarred, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprStarred, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2059,11 +1754,7 @@ impl FormatRule> for crate::expression::expr_name::FormatExprName { #[inline] - fn fmt( - &self, - node: &ast::ExprName, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprName, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2099,11 +1790,7 @@ impl FormatRule> for crate::expression::expr_list::FormatExprList { #[inline] - fn fmt( - &self, - node: &ast::ExprList, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprList, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2139,11 +1826,7 @@ impl FormatRule> for crate::expression::expr_tuple::FormatExprTuple { #[inline] - fn fmt( - &self, - node: &ast::ExprTuple, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprTuple, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2179,11 +1862,7 @@ impl FormatRule> for crate::expression::expr_slice::FormatExprSlice { #[inline] - fn fmt( - &self, - node: &ast::ExprSlice, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExprSlice, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2215,15 +1894,47 @@ impl<'ast> IntoFormat> for ast::ExprSlice { } } +impl FormatRule> + for crate::expression::expr_ipy_escape_command::FormatExprIpyEscapeCommand +{ + #[inline] + fn fmt(&self, node: &ast::ExprIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::ExprIpyEscapeCommand { + type Format<'a> = FormatRefWithRule< + 'a, + ast::ExprIpyEscapeCommand, + crate::expression::expr_ipy_escape_command::FormatExprIpyEscapeCommand, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::expression::expr_ipy_escape_command::FormatExprIpyEscapeCommand::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::ExprIpyEscapeCommand { + type Format = FormatOwnedWithRule< + ast::ExprIpyEscapeCommand, + crate::expression::expr_ipy_escape_command::FormatExprIpyEscapeCommand, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::expression::expr_ipy_escape_command::FormatExprIpyEscapeCommand::default(), + ) + } +} + impl FormatRule> for crate::other::except_handler_except_handler::FormatExceptHandlerExceptHandler { #[inline] - fn fmt( - &self, - node: &ast::ExceptHandlerExceptHandler, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ExceptHandlerExceptHandler, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2261,11 +1972,7 @@ impl FormatRule> for crate::pattern::pattern_match_value::FormatPatternMatchValue { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchValue, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchValue, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2301,11 +2008,7 @@ impl FormatRule> for crate::pattern::pattern_match_singleton::FormatPatternMatchSingleton { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchSingleton, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchSingleton, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2341,11 +2044,7 @@ impl FormatRule> for crate::pattern::pattern_match_sequence::FormatPatternMatchSequence { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchSequence, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchSequence, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2381,11 +2080,7 @@ impl FormatRule> for crate::pattern::pattern_match_mapping::FormatPatternMatchMapping { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchMapping, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchMapping, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2421,11 +2116,7 @@ impl FormatRule> for crate::pattern::pattern_match_class::FormatPatternMatchClass { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchClass, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchClass, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2461,11 +2152,7 @@ impl FormatRule> for crate::pattern::pattern_match_star::FormatPatternMatchStar { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchStar, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchStar, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2501,11 +2188,7 @@ impl FormatRule> for crate::pattern::pattern_match_as::FormatPatternMatchAs { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchAs, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchAs, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2541,11 +2224,7 @@ impl FormatRule> for crate::pattern::pattern_match_or::FormatPatternMatchOr { #[inline] - fn fmt( - &self, - node: &ast::PatternMatchOr, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::PatternMatchOr, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2581,11 +2260,7 @@ impl FormatRule> for crate::other::comprehension::FormatComprehension { #[inline] - fn fmt( - &self, - node: &ast::Comprehension, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::Comprehension, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2619,11 +2294,7 @@ impl<'ast> IntoFormat> for ast::Comprehension { impl FormatRule> for crate::other::arguments::FormatArguments { #[inline] - fn fmt( - &self, - node: &ast::Arguments, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::Arguments, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2649,70 +2320,103 @@ impl<'ast> IntoFormat> for ast::Arguments { } } -impl FormatRule> for crate::other::arg::FormatArg { +impl FormatRule> + for crate::other::parameters::FormatParameters +{ #[inline] - fn fmt(&self, node: &ast::Arg, f: &mut Formatter>) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) + fn fmt(&self, node: &ast::Parameters, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) } } -impl<'ast> AsFormat> for ast::Arg { - type Format<'a> = - FormatRefWithRule<'a, ast::Arg, crate::other::arg::FormatArg, PyFormatContext<'ast>>; +impl<'ast> AsFormat> for ast::Parameters { + type Format<'a> = FormatRefWithRule< + 'a, + ast::Parameters, + crate::other::parameters::FormatParameters, + PyFormatContext<'ast>, + >; fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new(self, crate::other::arg::FormatArg::default()) + FormatRefWithRule::new(self, crate::other::parameters::FormatParameters::default()) } } -impl<'ast> IntoFormat> for ast::Arg { - type Format = - FormatOwnedWithRule>; +impl<'ast> IntoFormat> for ast::Parameters { + type Format = FormatOwnedWithRule< + ast::Parameters, + crate::other::parameters::FormatParameters, + PyFormatContext<'ast>, + >; fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new(self, crate::other::arg::FormatArg::default()) + FormatOwnedWithRule::new(self, crate::other::parameters::FormatParameters::default()) } } -impl FormatRule> - for crate::other::arg_with_default::FormatArgWithDefault +impl FormatRule> for crate::other::parameter::FormatParameter { + #[inline] + fn fmt(&self, node: &ast::Parameter, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::Parameter { + type Format<'a> = FormatRefWithRule< + 'a, + ast::Parameter, + crate::other::parameter::FormatParameter, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new(self, crate::other::parameter::FormatParameter::default()) + } +} +impl<'ast> IntoFormat> for ast::Parameter { + type Format = FormatOwnedWithRule< + ast::Parameter, + crate::other::parameter::FormatParameter, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new(self, crate::other::parameter::FormatParameter::default()) + } +} + +impl FormatRule> + for crate::other::parameter_with_default::FormatParameterWithDefault { #[inline] - fn fmt( - &self, - node: &ast::ArgWithDefault, - f: &mut Formatter>, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) + fn fmt(&self, node: &ast::ParameterWithDefault, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) } } -impl<'ast> AsFormat> for ast::ArgWithDefault { +impl<'ast> AsFormat> for ast::ParameterWithDefault { type Format<'a> = FormatRefWithRule< 'a, - ast::ArgWithDefault, - crate::other::arg_with_default::FormatArgWithDefault, + ast::ParameterWithDefault, + crate::other::parameter_with_default::FormatParameterWithDefault, PyFormatContext<'ast>, >; fn format(&self) -> Self::Format<'_> { FormatRefWithRule::new( self, - crate::other::arg_with_default::FormatArgWithDefault::default(), + crate::other::parameter_with_default::FormatParameterWithDefault::default(), ) } } -impl<'ast> IntoFormat> for ast::ArgWithDefault { +impl<'ast> IntoFormat> for ast::ParameterWithDefault { type Format = FormatOwnedWithRule< - ast::ArgWithDefault, - crate::other::arg_with_default::FormatArgWithDefault, + ast::ParameterWithDefault, + crate::other::parameter_with_default::FormatParameterWithDefault, PyFormatContext<'ast>, >; fn into_format(self) -> Self::Format { FormatOwnedWithRule::new( self, - crate::other::arg_with_default::FormatArgWithDefault::default(), + crate::other::parameter_with_default::FormatParameterWithDefault::default(), ) } } impl FormatRule> for crate::other::keyword::FormatKeyword { #[inline] - fn fmt(&self, node: &ast::Keyword, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::Keyword, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2740,7 +2444,7 @@ impl<'ast> IntoFormat> for ast::Keyword { impl FormatRule> for crate::other::alias::FormatAlias { #[inline] - fn fmt(&self, node: &ast::Alias, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, node: &ast::Alias, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2761,11 +2465,7 @@ impl<'ast> IntoFormat> for ast::Alias { impl FormatRule> for crate::other::with_item::FormatWithItem { #[inline] - fn fmt( - &self, - node: &ast::WithItem, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::WithItem, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2793,11 +2493,7 @@ impl<'ast> IntoFormat> for ast::WithItem { impl FormatRule> for crate::other::match_case::FormatMatchCase { #[inline] - fn fmt( - &self, - node: &ast::MatchCase, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::MatchCase, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2825,11 +2521,7 @@ impl<'ast> IntoFormat> for ast::MatchCase { impl FormatRule> for crate::other::decorator::FormatDecorator { #[inline] - fn fmt( - &self, - node: &ast::Decorator, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::Decorator, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2859,11 +2551,7 @@ impl FormatRule> for crate::other::elif_else_clause::FormatElifElseClause { #[inline] - fn fmt( - &self, - node: &ast::ElifElseClause, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, node: &ast::ElifElseClause, f: &mut PyFormatter) -> FormatResult<()> { FormatNodeRule::::fmt(self, node, f) } } @@ -2894,3 +2582,147 @@ impl<'ast> IntoFormat> for ast::ElifElseClause { ) } } + +impl FormatRule> + for crate::type_param::type_params::FormatTypeParams +{ + #[inline] + fn fmt(&self, node: &ast::TypeParams, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::TypeParams { + type Format<'a> = FormatRefWithRule< + 'a, + ast::TypeParams, + crate::type_param::type_params::FormatTypeParams, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::type_param::type_params::FormatTypeParams::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::TypeParams { + type Format = FormatOwnedWithRule< + ast::TypeParams, + crate::type_param::type_params::FormatTypeParams, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::type_param::type_params::FormatTypeParams::default(), + ) + } +} + +impl FormatRule> + for crate::type_param::type_param_type_var::FormatTypeParamTypeVar +{ + #[inline] + fn fmt(&self, node: &ast::TypeParamTypeVar, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::TypeParamTypeVar { + type Format<'a> = FormatRefWithRule< + 'a, + ast::TypeParamTypeVar, + crate::type_param::type_param_type_var::FormatTypeParamTypeVar, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::type_param::type_param_type_var::FormatTypeParamTypeVar::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::TypeParamTypeVar { + type Format = FormatOwnedWithRule< + ast::TypeParamTypeVar, + crate::type_param::type_param_type_var::FormatTypeParamTypeVar, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::type_param::type_param_type_var::FormatTypeParamTypeVar::default(), + ) + } +} + +impl FormatRule> + for crate::type_param::type_param_type_var_tuple::FormatTypeParamTypeVarTuple +{ + #[inline] + fn fmt(&self, node: &ast::TypeParamTypeVarTuple, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::TypeParamTypeVarTuple { + type Format<'a> = FormatRefWithRule< + 'a, + ast::TypeParamTypeVarTuple, + crate::type_param::type_param_type_var_tuple::FormatTypeParamTypeVarTuple, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::type_param::type_param_type_var_tuple::FormatTypeParamTypeVarTuple::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::TypeParamTypeVarTuple { + type Format = FormatOwnedWithRule< + ast::TypeParamTypeVarTuple, + crate::type_param::type_param_type_var_tuple::FormatTypeParamTypeVarTuple, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::type_param::type_param_type_var_tuple::FormatTypeParamTypeVarTuple::default(), + ) + } +} + +impl FormatRule> + for crate::type_param::type_param_param_spec::FormatTypeParamParamSpec +{ + #[inline] + fn fmt(&self, node: &ast::TypeParamParamSpec, f: &mut PyFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl<'ast> AsFormat> for ast::TypeParamParamSpec { + type Format<'a> = FormatRefWithRule< + 'a, + ast::TypeParamParamSpec, + crate::type_param::type_param_param_spec::FormatTypeParamParamSpec, + PyFormatContext<'ast>, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::type_param::type_param_param_spec::FormatTypeParamParamSpec::default(), + ) + } +} +impl<'ast> IntoFormat> for ast::TypeParamParamSpec { + type Format = FormatOwnedWithRule< + ast::TypeParamParamSpec, + crate::type_param::type_param_param_spec::FormatTypeParamParamSpec, + PyFormatContext<'ast>, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::type_param::type_param_param_spec::FormatTypeParamParamSpec::default(), + ) + } +} diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index 89bf5493857e3..4303eac0d8f06 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -1,26 +1,25 @@ -use crate::comments::{ - dangling_node_comments, leading_node_comments, trailing_node_comments, Comments, -}; -use crate::context::PyFormatContext; -pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle}; +use thiserror::Error; + use ruff_formatter::format_element::tag; -use ruff_formatter::prelude::{ - dynamic_text, source_position, source_text_slice, text, ContainsNewlines, Formatter, Tag, -}; +use ruff_formatter::prelude::{source_position, text, Formatter, Tag}; use ruff_formatter::{ - format, normalize_newlines, write, Buffer, Format, FormatElement, FormatError, FormatResult, - PrintError, + format, write, Buffer, Format, FormatElement, FormatError, FormatResult, PrintError, }; use ruff_formatter::{Formatted, Printed, SourceCode}; -use ruff_python_ast::node::{AnyNodeRef, AstNode, NodeKind}; -use ruff_python_ast::{Mod, Ranged}; +use ruff_python_ast::node::{AnyNodeRef, AstNode}; +use ruff_python_ast::Mod; use ruff_python_index::{CommentRanges, CommentRangesBuilder}; use ruff_python_parser::lexer::{lex, LexicalError}; use ruff_python_parser::{parse_tokens, Mode, ParseError}; use ruff_source_file::Locator; -use ruff_text_size::{TextLen, TextRange}; -use std::borrow::Cow; -use thiserror::Error; +use ruff_text_size::TextLen; + +use crate::comments::{ + dangling_comments, leading_comments, trailing_comments, Comments, SourceComment, +}; +use crate::context::PyFormatContext; +pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle}; +use crate::verbatim::suppressed_node; pub(crate) mod builders; pub mod cli; @@ -34,42 +33,50 @@ pub(crate) mod other; pub(crate) mod pattern; mod prelude; pub(crate) mod statement; +pub(crate) mod type_param; +mod verbatim; include!("../../ruff_formatter/shared_traits.rs"); /// 'ast is the lifetime of the source code (input), 'buf is the lifetime of the buffer (output) pub(crate) type PyFormatter<'ast, 'buf> = Formatter<'buf, PyFormatContext<'ast>>; -/// Rule for formatting a JavaScript [`AstNode`]. +/// Rule for formatting a Python [`AstNode`]. pub(crate) trait FormatNodeRule where N: AstNode, { fn fmt(&self, node: &N, f: &mut PyFormatter) -> FormatResult<()> { - self.fmt_leading_comments(node, f)?; - self.fmt_node(node, f)?; - self.fmt_dangling_comments(node, f)?; - self.fmt_trailing_comments(node, f) - } - - /// Formats the node without comments. Ignores any suppression comments. - fn fmt_node(&self, node: &N, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [source_position(node.start())])?; - self.fmt_fields(node, f)?; - write!(f, [source_position(node.end())]) + let comments = f.context().comments().clone(); + + let node_comments = comments.leading_dangling_trailing(node.as_any_node_ref()); + + if self.is_suppressed(node_comments.trailing, f.context()) { + suppressed_node(node.as_any_node_ref()).fmt(f) + } else { + write!( + f, + [ + leading_comments(node_comments.leading), + source_position(node.start()) + ] + )?; + self.fmt_fields(node, f)?; + self.fmt_dangling_comments(node_comments.dangling, f)?; + + write!( + f, + [ + source_position(node.end()), + trailing_comments(node_comments.trailing) + ] + ) + } } /// Formats the node's fields. fn fmt_fields(&self, item: &N, f: &mut PyFormatter) -> FormatResult<()>; - /// Formats the [leading comments](comments#leading-comments) of the node. - /// - /// You may want to override this method if you want to manually handle the formatting of comments - /// inside of the `fmt_fields` method or customize the formatting of the leading comments. - fn fmt_leading_comments(&self, node: &N, f: &mut PyFormatter) -> FormatResult<()> { - leading_node_comments(node).fmt(f) - } - /// Formats the [dangling comments](comments#dangling-comments) of the node. /// /// You should override this method if the node handled by this rule can have dangling comments because the @@ -77,16 +84,20 @@ where /// no comments are dropped. /// /// A node can have dangling comments if all its children are tokens or if all node children are optional. - fn fmt_dangling_comments(&self, node: &N, f: &mut PyFormatter) -> FormatResult<()> { - dangling_node_comments(node).fmt(f) + fn fmt_dangling_comments( + &self, + dangling_node_comments: &[SourceComment], + f: &mut PyFormatter, + ) -> FormatResult<()> { + dangling_comments(dangling_node_comments).fmt(f) } - /// Formats the [trailing comments](comments#trailing-comments) of the node. - /// - /// You may want to override this method if you want to manually handle the formatting of comments - /// inside of the `fmt_fields` method or customize the formatting of the trailing comments. - fn fmt_trailing_comments(&self, node: &N, f: &mut PyFormatter) -> FormatResult<()> { - trailing_node_comments(node).fmt(f) + fn is_suppressed( + &self, + _trailing_comments: &[SourceComment], + _context: &PyFormatContext, + ) -> bool { + false } } @@ -149,111 +160,69 @@ pub fn format_node<'a>( let locator = Locator::new(source); - format!( + let formatted = format!( PyFormatContext::new(options, locator.contents(), comments), [root.format()] - ) + )?; + formatted + .context() + .comments() + .assert_all_formatted(SourceCode::new(source)); + Ok(formatted) } -pub(crate) struct NotYetImplemented(NodeKind); +pub(crate) struct NotYetImplementedCustomText<'a> { + text: &'static str, + node: AnyNodeRef<'a>, +} /// Formats a placeholder for nodes that have not yet been implemented -pub(crate) fn not_yet_implemented<'a, T>(node: T) -> NotYetImplemented +pub(crate) fn not_yet_implemented_custom_text<'a, T>( + text: &'static str, + node: T, +) -> NotYetImplementedCustomText<'a> where T: Into>, { - NotYetImplemented(node.into().kind()) -} - -impl Format> for NotYetImplemented { - fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { - let text = std::format!("NOT_YET_IMPLEMENTED_{:?}", self.0); - - f.write_element(FormatElement::Tag(Tag::StartVerbatim( - tag::VerbatimKind::Verbatim { - length: text.text_len(), - }, - )))?; - - f.write_element(FormatElement::DynamicText { - text: Box::from(text), - })?; - - f.write_element(FormatElement::Tag(Tag::EndVerbatim))?; - Ok(()) + NotYetImplementedCustomText { + text, + node: node.into(), } } -pub(crate) struct NotYetImplementedCustomText(&'static str); - -/// Formats a placeholder for nodes that have not yet been implemented -pub(crate) const fn not_yet_implemented_custom_text( - text: &'static str, -) -> NotYetImplementedCustomText { - NotYetImplementedCustomText(text) -} - -impl Format> for NotYetImplementedCustomText { +impl Format> for NotYetImplementedCustomText<'_> { fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { f.write_element(FormatElement::Tag(Tag::StartVerbatim( tag::VerbatimKind::Verbatim { - length: self.0.text_len(), + length: self.text.text_len(), }, - )))?; + ))); - text(self.0).fmt(f)?; + text(self.text).fmt(f)?; - f.write_element(FormatElement::Tag(Tag::EndVerbatim)) - } -} + f.write_element(FormatElement::Tag(Tag::EndVerbatim)); -pub(crate) struct VerbatimText(TextRange); + f.context() + .comments() + .mark_verbatim_node_comments_formatted(self.node); -#[allow(unused)] -pub(crate) fn verbatim_text(item: &T) -> VerbatimText -where - T: Ranged, -{ - VerbatimText(item.range()) -} - -impl Format> for VerbatimText { - fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { - f.write_element(FormatElement::Tag(Tag::StartVerbatim( - tag::VerbatimKind::Verbatim { - length: self.0.len(), - }, - )))?; - - match normalize_newlines(f.context().locator().slice(self.0), ['\r']) { - Cow::Borrowed(_) => { - write!(f, [source_text_slice(self.0, ContainsNewlines::Detect)])?; - } - Cow::Owned(cleaned) => { - write!( - f, - [ - dynamic_text(&cleaned, Some(self.0.start())), - source_position(self.0.end()) - ] - )?; - } - } - - f.write_element(FormatElement::Tag(Tag::EndVerbatim))?; Ok(()) } } #[cfg(test)] mod tests { - use crate::{format_module, format_node, PyFormatOptions}; + use std::path::Path; + use anyhow::Result; use insta::assert_snapshot; + use ruff_python_index::CommentRangesBuilder; use ruff_python_parser::lexer::lex; use ruff_python_parser::{parse_tokens, Mode}; + use crate::{format_module, format_node, PyFormatOptions}; + /// Very basic test intentionally kept very similar to the CLI #[test] fn basic() -> Result<()> { @@ -280,31 +249,10 @@ if True: #[test] fn quick_test() { let src = r#" -with ( - [ - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "bbbbbbbbbb", - "cccccccccccccccccccccccccccccccccccccccccc", - dddddddddddddddddddddddddddddddd, - ] as example1, - aaaaaaaaaaaaaaaaaaaaaaaaaa - + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - + cccccccccccccccccccccccccccc - + ddddddddddddddddd as example2, - CtxManager2() as example2, - CtxManager2() as example2, - CtxManager2() as example2, -): - ... - -with [ - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "bbbbbbbbbb", - "cccccccccccccccccccccccccccccccccccccccccc", - dddddddddddddddddddddddddddddddd, -] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2: +for converter in connection.ops.get_db_converters( + expression +) + expression.get_db_converters(connection): ... - "#; // Tokenize once let mut tokens = Vec::new(); @@ -319,23 +267,18 @@ with [ let comment_ranges = comment_ranges.finish(); // Parse the AST. - let python_ast = parse_tokens(tokens, Mode::Module, "").unwrap(); - - let formatted = format_node( - &python_ast, - &comment_ranges, - src, - PyFormatOptions::default(), - ) - .unwrap(); + let source_path = "code_inline.py"; + let python_ast = parse_tokens(tokens, Mode::Module, source_path).unwrap(); + let options = PyFormatOptions::from_extension(Path::new(source_path)); + let formatted = format_node(&python_ast, &comment_ranges, src, options).unwrap(); // Uncomment the `dbg` to print the IR. // Use `dbg_write!(f, []) instead of `write!(f, [])` in your formatting code to print some IR // inside of a `Format` implementation // use ruff_formatter::FormatContext; - // dbg!(formatted + // formatted // .document() - // .display(formatted.context().source_code())); + // .display(formatted.context().source_code()); // // dbg!(formatted // .context() @@ -346,9 +289,10 @@ with [ assert_eq!( printed.as_code(), - r#"while True: - if something.changed: - do.stuff() # trailing comment + r#"for converter in connection.ops.get_db_converters( + expression +) + expression.get_db_converters(connection): + ... "# ); } diff --git a/crates/ruff_python_formatter/src/main.rs b/crates/ruff_python_formatter/src/main.rs index 63b789888cc99..ba74dd06c3692 100644 --- a/crates/ruff_python_formatter/src/main.rs +++ b/crates/ruff_python_formatter/src/main.rs @@ -1,4 +1,5 @@ use std::io::{stdout, Read, Write}; +use std::path::Path; use std::{fs, io}; use anyhow::{bail, Context, Result}; @@ -25,7 +26,8 @@ fn main() -> Result<()> { ); } let input = read_from_stdin()?; - let formatted = format_and_debug_print(&input, &cli)?; + // It seems reasonable to give this a dummy name + let formatted = format_and_debug_print(&input, &cli, Path::new("stdin.py"))?; if cli.check { if formatted == input { return Ok(()); @@ -37,7 +39,7 @@ fn main() -> Result<()> { for file in &cli.files { let input = fs::read_to_string(file) .with_context(|| format!("Could not read {}: ", file.display()))?; - let formatted = format_and_debug_print(&input, &cli)?; + let formatted = format_and_debug_print(&input, &cli, file)?; match cli.emit { Some(Emit::Stdout) => stdout().lock().write_all(formatted.as_bytes())?, None | Some(Emit::Files) => { diff --git a/crates/ruff_python_formatter/src/module/mod_module.rs b/crates/ruff_python_formatter/src/module/mod_module.rs index 61556fe1ec802..654c92aa9bd98 100644 --- a/crates/ruff_python_formatter/src/module/mod_module.rs +++ b/crates/ruff_python_formatter/src/module/mod_module.rs @@ -1,4 +1,4 @@ -use crate::statement::suite::SuiteLevel; +use crate::statement::suite::SuiteKind; use crate::{AsFormat, FormatNodeRule, PyFormatter}; use ruff_formatter::prelude::hard_line_break; use ruff_formatter::{write, Buffer, FormatResult}; @@ -13,7 +13,7 @@ impl FormatNodeRule for FormatModModule { write!( f, [ - body.format().with_options(SuiteLevel::TopLevel), + body.format().with_options(SuiteKind::TopLevel), // Trailing newline at the end of the file hard_line_break() ] diff --git a/crates/ruff_python_formatter/src/options.rs b/crates/ruff_python_formatter/src/options.rs index 65bcf655527c5..ee427fd312829 100644 --- a/crates/ruff_python_formatter/src/options.rs +++ b/crates/ruff_python_formatter/src/options.rs @@ -1,5 +1,8 @@ use ruff_formatter::printer::{LineEnding, PrinterOptions}; use ruff_formatter::{FormatOptions, IndentStyle, LineWidth}; +use ruff_python_ast::PySourceType; +use std::path::Path; +use std::str::FromStr; #[derive(Clone, Debug)] #[cfg_attr( @@ -8,9 +11,13 @@ use ruff_formatter::{FormatOptions, IndentStyle, LineWidth}; serde(default) )] pub struct PyFormatOptions { + /// Whether we're in a `.py` file or `.pyi` file, which have different rules. + source_type: PySourceType, + /// Specifies the indent style: /// * Either a tab /// * or a specific amount of spaces + #[cfg_attr(feature = "serde", serde(default = "default_indent_style"))] indent_style: IndentStyle, /// The preferred line width at which the formatter should wrap lines. @@ -20,7 +27,7 @@ pub struct PyFormatOptions { /// The preferred quote style to use (single vs double quotes). quote_style: QuoteStyle, - /// Whether to expand lists or elements if they have a trailing comma such as `(a, b,)` + /// Whether to expand lists or elements if they have a trailing comma such as `(a, b,)`. magic_trailing_comma: MagicTrailingComma, } @@ -28,7 +35,35 @@ fn default_line_width() -> LineWidth { LineWidth::try_from(88).unwrap() } +fn default_indent_style() -> IndentStyle { + IndentStyle::Space(4) +} + +impl Default for PyFormatOptions { + fn default() -> Self { + Self { + source_type: PySourceType::default(), + indent_style: default_indent_style(), + line_width: default_line_width(), + quote_style: QuoteStyle::default(), + magic_trailing_comma: MagicTrailingComma::default(), + } + } +} + impl PyFormatOptions { + /// Otherwise sets the defaults. Returns none if the extension is unknown + pub fn from_extension(path: &Path) -> Self { + Self::from_source_type(PySourceType::from(path)) + } + + pub fn from_source_type(source_type: PySourceType) -> Self { + Self { + source_type, + ..Self::default() + } + } + pub fn magic_trailing_comma(&self) -> MagicTrailingComma { self.magic_trailing_comma } @@ -37,22 +72,30 @@ impl PyFormatOptions { self.quote_style } - pub fn with_quote_style(&mut self, style: QuoteStyle) -> &mut Self { + pub fn source_type(&self) -> PySourceType { + self.source_type + } + + #[must_use] + pub fn with_quote_style(mut self, style: QuoteStyle) -> Self { self.quote_style = style; self } - pub fn with_magic_trailing_comma(&mut self, trailing_comma: MagicTrailingComma) -> &mut Self { + #[must_use] + pub fn with_magic_trailing_comma(mut self, trailing_comma: MagicTrailingComma) -> Self { self.magic_trailing_comma = trailing_comma; self } - pub fn with_indent_style(&mut self, indent_style: IndentStyle) -> &mut Self { + #[must_use] + pub fn with_indent_style(mut self, indent_style: IndentStyle) -> Self { self.indent_style = indent_style; self } - pub fn with_line_width(&mut self, line_width: LineWidth) -> &mut Self { + #[must_use] + pub fn with_line_width(mut self, line_width: LineWidth) -> Self { self.line_width = line_width; self } @@ -77,17 +120,6 @@ impl FormatOptions for PyFormatOptions { } } -impl Default for PyFormatOptions { - fn default() -> Self { - Self { - indent_style: IndentStyle::Space(4), - line_width: LineWidth::try_from(88).unwrap(), - quote_style: QuoteStyle::default(), - magic_trailing_comma: MagicTrailingComma::default(), - } - } -} - #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr( feature = "serde", @@ -129,6 +161,19 @@ impl TryFrom for QuoteStyle { } } +impl FromStr for QuoteStyle { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "\"" | "double" | "Double" => Ok(Self::Double), + "'" | "single" | "Single" => Ok(Self::Single), + // TODO: replace this error with a diagnostic + _ => Err("Value not supported for QuoteStyle"), + } + } +} + #[derive(Copy, Clone, Debug, Default)] #[cfg_attr( feature = "serde", @@ -146,3 +191,16 @@ impl MagicTrailingComma { matches!(self, Self::Respect) } } + +impl FromStr for MagicTrailingComma { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "respect" | "Respect" => Ok(Self::Respect), + "ignore" | "Ignore" => Ok(Self::Ignore), + // TODO: replace this error with a diagnostic + _ => Err("Value not supported for MagicTrailingComma"), + } + } +} diff --git a/crates/ruff_python_formatter/src/other/arg_with_default.rs b/crates/ruff_python_formatter/src/other/arg_with_default.rs deleted file mode 100644 index 3864c068891ae..0000000000000 --- a/crates/ruff_python_formatter/src/other/arg_with_default.rs +++ /dev/null @@ -1,27 +0,0 @@ -use ruff_formatter::write; -use ruff_python_ast::ArgWithDefault; - -use crate::prelude::*; -use crate::FormatNodeRule; - -#[derive(Default)] -pub struct FormatArgWithDefault; - -impl FormatNodeRule for FormatArgWithDefault { - fn fmt_fields(&self, item: &ArgWithDefault, f: &mut PyFormatter) -> FormatResult<()> { - let ArgWithDefault { - range: _, - def, - default, - } = item; - - write!(f, [def.format()])?; - - if let Some(default) = default { - let space = def.annotation.is_some().then_some(space()); - write!(f, [space, text("="), space, group(&default.format())])?; - } - - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/other/arguments.rs b/crates/ruff_python_formatter/src/other/arguments.rs index 9f90dfb25dca9..6c03eb46e8819 100644 --- a/crates/ruff_python_formatter/src/other/arguments.rs +++ b/crates/ruff_python_formatter/src/other/arguments.rs @@ -1,614 +1,139 @@ -use std::usize; - -use ruff_python_ast::{Arguments, Ranged}; +use crate::comments::SourceComment; +use ruff_formatter::write; +use ruff_python_ast::node::AstNode; +use ruff_python_ast::{Arguments, Expr, Ranged}; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{TextRange, TextSize}; -use ruff_formatter::{format_args, write, FormatRuleWithOptions}; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; -use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; - -use crate::comments::{ - dangling_comments, leading_comments, leading_node_comments, trailing_comments, - CommentLinePosition, SourceComment, -}; -use crate::context::{NodeLevel, WithNodeLevel}; -use crate::expression::parentheses::parenthesized; +use crate::expression::expr_generator_exp::GeneratorExpParentheses; +use crate::expression::parentheses::{empty_parenthesized, parenthesized, Parentheses}; use crate::prelude::*; use crate::FormatNodeRule; -#[derive(Eq, PartialEq, Debug, Default)] -pub enum ArgumentsParentheses { - /// By default, arguments will always preserve their surrounding parentheses. - #[default] - Preserve, - - /// Handle special cases where parentheses should never be used. - /// - /// An example where parentheses are never used for arguments would be with lambda - /// expressions. The following is invalid syntax: - /// ```python - /// lambda (x, y, z): ... - /// ``` - /// Instead the lambda here should be: - /// ```python - /// lambda x, y, z: ... - /// ``` - Never, -} - #[derive(Default)] -pub struct FormatArguments { - parentheses: ArgumentsParentheses, -} - -impl FormatRuleWithOptions> for FormatArguments { - type Options = ArgumentsParentheses; - - fn with_options(mut self, options: Self::Options) -> Self { - self.parentheses = options; - self - } -} +pub struct FormatArguments; impl FormatNodeRule for FormatArguments { fn fmt_fields(&self, item: &Arguments, f: &mut PyFormatter) -> FormatResult<()> { - let Arguments { - range: _, - posonlyargs, - args, - vararg, - kwonlyargs, - kwarg, - } = item; - - let comments = f.context().comments().clone(); - let dangling = comments.dangling_comments(item); - let (slash, star) = find_argument_separators(f.context().source(), item); - - let format_inner = format_with(|f: &mut PyFormatter| { - let separator = format_with(|f| write!(f, [text(","), soft_line_break_or_space()])); - let mut joiner = f.join_with(separator); - let mut last_node: Option = None; - - for arg_with_default in posonlyargs { - joiner.entry(&arg_with_default.format()); - - last_node = Some(arg_with_default.into()); - } - - let slash_comments_end = if posonlyargs.is_empty() { - 0 - } else { - let slash_comments_end = dangling.partition_point(|comment| { - let assignment = assign_argument_separator_comment_placement( - slash.as_ref(), - star.as_ref(), - comment.slice().range(), - comment.line_position(), - ) - .expect("Unexpected dangling comment type in function arguments"); - matches!( - assignment, - ArgumentSeparatorCommentLocation::SlashLeading - | ArgumentSeparatorCommentLocation::SlashTrailing - ) - }); - joiner.entry(&CommentsAroundText { - text: "/", - comments: &dangling[..slash_comments_end], - }); - slash_comments_end - }; - - for arg_with_default in args { - joiner.entry(&arg_with_default.format()); - - last_node = Some(arg_with_default.into()); - } - - // kw only args need either a `*args` ahead of them capturing all var args or a `*` - // pseudo-argument capturing all fields. We can also have `*args` without any kwargs - // afterwards. - if let Some(vararg) = vararg { - joiner.entry(&format_args![ - leading_node_comments(vararg.as_ref()), - text("*"), - vararg.format() - ]); - last_node = Some(vararg.as_any_node_ref()); - } else if !kwonlyargs.is_empty() { - // Given very strange comment placement, comments here may not actually have been - // marked as `StarLeading`/`StarTrailing`, but that's fine since we still produce - // a stable formatting in this case - // ```python - // def f42( - // a, - // / # 1 - // # 2 - // , # 3 - // # 4 - // * # 5 - // , # 6 - // c, - // ): - // pass - // ``` - joiner.entry(&CommentsAroundText { - text: "*", - comments: &dangling[slash_comments_end..], - }); - } - - for arg_with_default in kwonlyargs { - joiner.entry(&arg_with_default.format()); - - last_node = Some(arg_with_default.into()); - } - - if let Some(kwarg) = kwarg { - joiner.entry(&format_args![ - leading_node_comments(kwarg.as_ref()), - text("**"), - kwarg.format() - ]); - last_node = Some(kwarg.as_any_node_ref()); - } - - joiner.finish()?; + // We have a case with `f()` without any argument, which is a special case because we can + // have a comment with no node attachment inside: + // ```python + // f( + // # This call has a dangling comment. + // ) + // ``` + if item.args.is_empty() && item.keywords.is_empty() { + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + return write!(f, [empty_parenthesized("(", dangling, ")")]); + } - // Functions use the regular magic trailing comma logic, lambdas may or may not have - // a trailing comma but it's just preserved without any magic. - // ```python - // # Add magic trailing comma if its expands - // def f(a): pass - // # Expands if magic trailing comma setting is respect, otherwise remove the comma - // def g(a,): pass - // # Never expands - // x1 = lambda y: 1 - // # Never expands, the comma is always preserved - // x2 = lambda y,: 1 - // ``` - if self.parentheses == ArgumentsParentheses::Never { - // For lambdas (no parentheses), preserve the trailing comma. It doesn't - // behave like a magic trailing comma, it's just preserved - if has_trailing_comma(item, last_node, f.context().source()) { - write!(f, [text(",")])?; + let all_arguments = format_with(|f: &mut PyFormatter| { + let source = f.context().source(); + let mut joiner = f.join_comma_separated(item.end()); + match item.args.as_slice() { + [arg] if item.keywords.is_empty() => { + match arg { + Expr::GeneratorExp(generator_exp) => joiner.entry( + generator_exp, + &generator_exp + .format() + .with_options(GeneratorExpParentheses::StripIfOnlyFunctionArg), + ), + other => { + let parentheses = + if is_single_argument_parenthesized(arg, item.end(), source) { + Parentheses::Always + } else { + // Note: no need to handle opening-parenthesis comments, since + // an opening-parenthesis comment implies that the argument is + // parenthesized. + Parentheses::Never + }; + joiner.entry(other, &other.format().with_options(parentheses)) + } + }; } - } else { - write!(f, [if_group_breaks(&text(","))])?; - - if f.options().magic_trailing_comma().is_respect() - && has_trailing_comma(item, last_node, f.context().source()) - { - // Make the magic trailing comma expand the group - write!(f, [hard_line_break()])?; + args => { + joiner + .entries( + // We have the parentheses from the call so the item never need any + args.iter() + .map(|arg| (arg, arg.format().with_options(Parentheses::Preserve))), + ) + .nodes(item.keywords.iter()); } } - Ok(()) + joiner.finish() }); - let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f); - - let num_arguments = posonlyargs.len() - + args.len() - + usize::from(vararg.is_some()) - + kwonlyargs.len() - + usize::from(kwarg.is_some()); + // If the arguments are non-empty, then a dangling comment indicates a comment on the + // same line as the opening parenthesis, e.g.: + // ```python + // f( # This call has a dangling comment. + // a, + // b, + // c, + // ) + let comments = f.context().comments().clone(); + let dangling_comments = comments.dangling(item.as_any_node_ref()); - if self.parentheses == ArgumentsParentheses::Never { - write!(f, [group(&format_inner)]) - } else if num_arguments == 0 { - // No arguments, format any dangling comments between `()` - write!( - f, - [ - text("("), - block_indent(&dangling_comments(dangling)), - text(")") - ] - ) - } else { - write!(f, [parenthesized("(", &group(&format_inner), ")")]) - } + write!( + f, + [ + // The outer group is for things like: + // ```python + // get_collection( + // hey_this_is_a_very_long_call, + // it_has_funny_attributes_asdf_asdf, + // too_long_for_the_line, + // really=True, + // ) + // ``` + // The inner group is for things like: + // ```python + // get_collection( + // hey_this_is_a_very_long_call, it_has_funny_attributes_asdf_asdf, really=True + // ) + // ``` + parenthesized("(", &group(&all_arguments), ")") + .with_dangling_comments(dangling_comments) + ] + ) } - fn fmt_dangling_comments(&self, _node: &Arguments, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled in `fmt_fields` Ok(()) } } -struct CommentsAroundText<'a> { - text: &'static str, - comments: &'a [SourceComment], -} - -impl Format> for CommentsAroundText<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - if self.comments.is_empty() { - text(self.text).fmt(f) - } else { - // There might be own line comments in trailing, but those are weird and we can kinda - // ignore them - // ```python - // def f42( - // a, - // # leading comment (own line) - // / # first trailing comment (end-of-line) - // # trailing own line comment - // , - // c, - // ): - // ``` - let (leading, trailing) = self.comments.split_at( - self.comments - .partition_point(|comment| comment.line_position().is_own_line()), - ); - write!( - f, - [ - leading_comments(leading), - text(self.text), - trailing_comments(trailing) - ] - ) - } - } -} - -/// `/` and `*` in a function signature -/// -/// ```text -/// def f(arg_a, /, arg_b, *, arg_c): pass -/// ^ ^ ^ ^ ^ ^ slash preceding end -/// ^ ^ ^ ^ ^ slash (a separator) -/// ^ ^ ^ ^ slash following start -/// ^ ^ ^ star preceding end -/// ^ ^ star (a separator) -/// ^ star following start -/// ``` -#[derive(Debug)] -pub(crate) struct ArgumentSeparator { - /// The end of the last node or separator before this separator - pub(crate) preceding_end: TextSize, - /// The range of the separator itself - pub(crate) separator: TextRange, - /// The start of the first node or separator following this separator - pub(crate) following_start: TextSize, -} - -/// Finds slash and star in `f(a, /, b, *, c)` -/// -/// Returns slash and star -pub(crate) fn find_argument_separators( - contents: &str, - arguments: &Arguments, -) -> (Option, Option) { - // We only compute preceding_end and token location here since following_start depends on the - // star location, but the star location depends on slash's position - let slash = if let Some(preceding_end) = arguments.posonlyargs.last().map(Ranged::end) { - // ```text - // def f(a1=1, a2=2, /, a3, a4): pass - // ^^^^^^^^^^^ the range (defaults) - // def f(a1, a2, /, a3, a4): pass - // ^^^^^^^^^^^^ the range (no default) - // ``` - let range = TextRange::new(preceding_end, arguments.end()); - let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia(); - - let comma = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(comma.kind() == SimpleTokenKind::Comma, "{comma:?}"); - let slash = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(slash.kind() == SimpleTokenKind::Slash, "{slash:?}"); - - Some((preceding_end, slash.range)) - } else { - None - }; - - // If we have a vararg we have a node that the comments attach to - let star = if arguments.vararg.is_some() { - // When the vararg is present the comments attach there and we don't need to do manual - // formatting - None - } else if let Some(first_keyword_argument) = arguments.kwonlyargs.first() { - // Check in that order: - // * `f(a, /, b, *, c)` and `f(a=1, /, b=2, *, c)` - // * `f(a, /, *, b)` - // * `f(*, b)` (else branch) - let after_arguments = arguments - .args - .last() - .map(|arg| arg.range.end()) - .or(slash.map(|(_, slash)| slash.end())); - if let Some(preceding_end) = after_arguments { - let range = TextRange::new(preceding_end, arguments.end()); - let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia(); - - let comma = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(comma.kind() == SimpleTokenKind::Comma, "{comma:?}"); - let star = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(star.kind() == SimpleTokenKind::Star, "{star:?}"); - - Some(ArgumentSeparator { - preceding_end, - separator: star.range, - following_start: first_keyword_argument.start(), - }) - } else { - let mut tokens = SimpleTokenizer::new(contents, arguments.range).skip_trivia(); - - let lparen = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(lparen.kind() == SimpleTokenKind::LParen, "{lparen:?}"); - let star = tokens - .next() - .expect("The function definition can't end here"); - debug_assert!(star.kind() == SimpleTokenKind::Star, "{star:?}"); - Some(ArgumentSeparator { - preceding_end: arguments.range.start(), - separator: star.range, - following_start: first_keyword_argument.start(), - }) - } - } else { - None - }; - - // Now that we have star, compute how long slash trailing comments can go - // Check in that order: - // * `f(a, /, b)` - // * `f(a, /, *b)` - // * `f(a, /, *, b)` - // * `f(a, /)` - let slash_following_start = arguments - .args - .first() - .map(Ranged::start) - .or(arguments.vararg.as_ref().map(|first| first.start())) - .or(star.as_ref().map(|star| star.separator.start())) - .unwrap_or(arguments.end()); - let slash = slash.map(|(preceding_end, slash)| ArgumentSeparator { - preceding_end, - separator: slash, - following_start: slash_following_start, - }); - - (slash, star) -} +fn is_single_argument_parenthesized(argument: &Expr, call_end: TextSize, source: &str) -> bool { + let mut has_seen_r_paren = false; -/// Locates positional only arguments separator `/` or the keywords only arguments -/// separator `*` comments. -/// -/// ```python -/// def test( -/// a, -/// # Positional only arguments after here -/// /, # trailing positional argument comment. -/// b, -/// ): -/// pass -/// ``` -/// or -/// ```python -/// def f( -/// a="", -/// # Keyword only arguments only after here -/// *, # trailing keyword argument comment. -/// b="", -/// ): -/// pass -/// ``` -/// or -/// ```python -/// def f( -/// a, -/// # positional only comment, leading -/// /, # positional only comment, trailing -/// b, -/// # keyword only comment, leading -/// *, # keyword only comment, trailing -/// c, -/// ): -/// pass -/// ``` -/// Notably, the following is possible: -/// ```python -/// def f32( -/// a, -/// # positional only comment, leading -/// /, # positional only comment, trailing -/// # keyword only comment, leading -/// *, # keyword only comment, trailing -/// c, -/// ): -/// pass -/// ``` -/// -/// ## Background -/// -/// ```text -/// def f(a1, a2): pass -/// ^^^^^^ arguments (args) -/// ``` -/// Use a star to separate keyword only arguments: -/// ```text -/// def f(a1, a2, *, a3, a4): pass -/// ^^^^^^ arguments (args) -/// ^^^^^^ keyword only arguments (kwargs) -/// ``` -/// Use a slash to separate positional only arguments. Note that this changes the arguments left -/// of the slash while the star change the arguments right of it: -/// ```text -/// def f(a1, a2, /, a3, a4): pass -/// ^^^^^^ positional only arguments (posonlyargs) -/// ^^^^^^ arguments (args) -/// ``` -/// You can combine both: -/// ```text -/// def f(a1, a2, /, a3, a4, *, a5, a6): pass -/// ^^^^^^ positional only arguments (posonlyargs) -/// ^^^^^^ arguments (args) -/// ^^^^^^ keyword only arguments (kwargs) -/// ``` -/// They can all have defaults, meaning that the preceding node ends at the default instead of the -/// argument itself: -/// ```text -/// def f(a1=1, a2=2, /, a3=3, a4=4, *, a5=5, a6=6): pass -/// ^ ^ ^ ^ ^ ^ defaults -/// ^^^^^^^^^^ positional only arguments (posonlyargs) -/// ^^^^^^^^^^ arguments (args) -/// ^^^^^^^^^^ keyword only arguments (kwargs) -/// ``` -/// An especially difficult case is having no regular arguments, so comments from both slash and -/// star will attach to either a2 or a3 and the next token is incorrect. -/// ```text -/// def f(a1, a2, /, *, a3, a4): pass -/// ^^^^^^ positional only arguments (posonlyargs) -/// ^^^^^^ keyword only arguments (kwargs) -/// ``` -pub(crate) fn assign_argument_separator_comment_placement( - slash: Option<&ArgumentSeparator>, - star: Option<&ArgumentSeparator>, - comment_range: TextRange, - text_position: CommentLinePosition, -) -> Option { - if let Some(ArgumentSeparator { - preceding_end, - separator: slash, - following_start, - }) = slash + for token in + SimpleTokenizer::new(source, TextRange::new(argument.end(), call_end)).skip_trivia() { - // ```python - // def f( - // # start too early - // a, # not own line - // # this is the one - // /, # too late (handled later) - // b, - // ) - // ``` - if comment_range.start() > *preceding_end - && comment_range.start() < slash.start() - && text_position.is_own_line() - { - return Some(ArgumentSeparatorCommentLocation::SlashLeading); - } - - // ```python - // def f( - // a, - // # too early (handled above) - // /, # this is the one - // # not end-of-line - // b, - // ) - // ``` - if comment_range.start() > slash.end() - && comment_range.start() < *following_start - && text_position.is_end_of_line() - { - return Some(ArgumentSeparatorCommentLocation::SlashTrailing); - } - } - - if let Some(ArgumentSeparator { - preceding_end, - separator: star, - following_start, - }) = star - { - // ```python - // def f( - // # start too early - // a, # not own line - // # this is the one - // *, # too late (handled later) - // b, - // ) - // ``` - if comment_range.start() > *preceding_end - && comment_range.start() < star.start() - && text_position.is_own_line() - { - return Some(ArgumentSeparatorCommentLocation::StarLeading); - } - - // ```python - // def f( - // a, - // # too early (handled above) - // *, # this is the one - // # not end-of-line - // b, - // ) - // ``` - if comment_range.start() > star.end() - && comment_range.start() < *following_start - && text_position.is_end_of_line() - { - return Some(ArgumentSeparatorCommentLocation::StarTrailing); + match token.kind() { + SimpleTokenKind::RParen => { + if has_seen_r_paren { + return true; + } + has_seen_r_paren = true; + } + // Skip over any trailing comma + SimpleTokenKind::Comma => continue, + _ => { + // Passed the arguments + break; + } } } - None -} - -/// ```python -/// def f( -/// a, -/// # before slash -/// /, # after slash -/// b, -/// # before star -/// *, # after star -/// c, -/// ): -/// pass -/// ``` -#[derive(Debug)] -pub(crate) enum ArgumentSeparatorCommentLocation { - SlashLeading, - SlashTrailing, - StarLeading, - StarTrailing, -} - -fn has_trailing_comma(arguments: &Arguments, last_node: Option, source: &str) -> bool { - // No nodes, no trailing comma - let Some(last_node) = last_node else { - return false; - }; - - let ends_with_pos_only_argument_separator = !arguments.posonlyargs.is_empty() - && arguments.args.is_empty() - && arguments.vararg.is_none() - && arguments.kwonlyargs.is_empty() - && arguments.kwarg.is_none(); - - let mut tokens = SimpleTokenizer::starts_at(last_node.end(), source).skip_trivia(); - // `def a(b, c, /): ... ` - // The slash lacks its own node - if ends_with_pos_only_argument_separator { - let comma = tokens.next(); - assert!(matches!(comma, Some(SimpleToken { kind: SimpleTokenKind::Comma, .. })), "The last positional only argument must be separated by a `,` from the positional only arguments separator `/` but found '{comma:?}'."); - - let slash = tokens.next(); - assert!(matches!(slash, Some(SimpleToken { kind: SimpleTokenKind::Slash, .. })), "The positional argument separator must be present for a function that has positional only arguments but found '{slash:?}'."); - } - tokens - .next() - .expect("There must be a token after the argument list") - .kind() - == SimpleTokenKind::Comma + false } diff --git a/crates/ruff_python_formatter/src/other/commas.rs b/crates/ruff_python_formatter/src/other/commas.rs new file mode 100644 index 0000000000000..326daba4255b5 --- /dev/null +++ b/crates/ruff_python_formatter/src/other/commas.rs @@ -0,0 +1,31 @@ +use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::TextRange; + +use crate::prelude::*; +use crate::{MagicTrailingComma, PyFormatOptions}; + +/// Returns `true` if the range ends with a magic trailing comma (and the magic trailing comma +/// should be respected). +pub(crate) fn has_magic_trailing_comma( + range: TextRange, + options: &PyFormatOptions, + context: &PyFormatContext, +) -> bool { + match options.magic_trailing_comma() { + MagicTrailingComma::Respect => { + let first_token = SimpleTokenizer::new(context.source(), range) + .skip_trivia() + // Skip over any closing parentheses belonging to the expression + .find(|token| token.kind() != SimpleTokenKind::RParen); + + matches!( + first_token, + Some(SimpleToken { + kind: SimpleTokenKind::Comma, + .. + }) + ) + } + MagicTrailingComma::Ignore => false, + } +} diff --git a/crates/ruff_python_formatter/src/other/comprehension.rs b/crates/ruff_python_formatter/src/other/comprehension.rs index e5565ebb2195a..a71cca2b2ddf4 100644 --- a/crates/ruff_python_formatter/src/other/comprehension.rs +++ b/crates/ruff_python_formatter/src/other/comprehension.rs @@ -1,4 +1,4 @@ -use crate::comments::{leading_comments, trailing_comments}; +use crate::comments::{leading_comments, trailing_comments, SourceComment}; use crate::expression::expr_tuple::TupleParentheses; use crate::prelude::*; use crate::AsFormat; @@ -15,7 +15,7 @@ impl FormatNodeRule for FormatComprehension { impl Format> for Spacer<'_> { fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { - if f.context().comments().has_leading_comments(self.0) { + if f.context().comments().has_leading(self.0) { soft_line_break_or_space().fmt(f) } else { space().fmt(f) @@ -36,13 +36,13 @@ impl FormatNodeRule for FormatComprehension { } let comments = f.context().comments().clone(); - let dangling_item_comments = comments.dangling_comments(item); + let dangling_item_comments = comments.dangling(item); let (before_target_comments, before_in_comments) = dangling_item_comments.split_at( dangling_item_comments - .partition_point(|comment| comment.slice().end() < target.range().start()), + .partition_point(|comment| comment.slice().end() < target.start()), ); - let trailing_in_comments = comments.dangling_comments(iter); + let trailing_in_comments = comments.dangling(iter); let in_spacer = format_with(|f| { if before_in_comments.is_empty() { @@ -73,7 +73,7 @@ impl FormatNodeRule for FormatComprehension { let joined = format_with(|f| { let mut joiner = f.join_with(soft_line_break_or_space()); for if_case in ifs { - let dangling_if_comments = comments.dangling_comments(if_case); + let dangling_if_comments = comments.dangling(if_case); let (own_line_if_comments, end_of_line_if_comments) = dangling_if_comments .split_at( @@ -98,7 +98,7 @@ impl FormatNodeRule for FormatComprehension { fn fmt_dangling_comments( &self, - _node: &Comprehension, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { // dangling comments are formatted as part of fmt_fields @@ -109,7 +109,7 @@ impl FormatNodeRule for FormatComprehension { struct ExprTupleWithoutParentheses<'a>(&'a Expr); impl Format> for ExprTupleWithoutParentheses<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { match self.0 { Expr::Tuple(expr_tuple) => expr_tuple .format() diff --git a/crates/ruff_python_formatter/src/other/decorator.rs b/crates/ruff_python_formatter/src/other/decorator.rs index 9e6ef4219a612..5ff346fa0fc54 100644 --- a/crates/ruff_python_formatter/src/other/decorator.rs +++ b/crates/ruff_python_formatter/src/other/decorator.rs @@ -1,3 +1,4 @@ +use crate::comments::{SourceComment, SuppressionKind}; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; @@ -23,4 +24,12 @@ impl FormatNodeRule for FormatDecorator { ] ) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs b/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs index 052710e7c26b2..acdf88fcd0027 100644 --- a/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs +++ b/crates/ruff_python_formatter/src/other/except_handler_except_handler.rs @@ -1,11 +1,13 @@ -use crate::comments::trailing_comments; +use ruff_formatter::FormatRuleWithOptions; +use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::ExceptHandlerExceptHandler; + +use crate::comments::SourceComment; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::FormatRuleWithOptions; -use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::ExceptHandlerExceptHandler; #[derive(Copy, Clone, Default)] pub enum ExceptHandlerKind { @@ -44,44 +46,54 @@ impl FormatNodeRule for FormatExceptHandlerExceptHan } = item; let comments_info = f.context().comments().clone(); - let dangling_comments = comments_info.dangling_comments(item); + let dangling_comments = comments_info.dangling(item); write!( f, [ - text("except"), - match self.except_handler_kind { - ExceptHandlerKind::Regular => None, - ExceptHandlerKind::Starred => Some(text("*")), - } - ] - )?; + clause_header( + ClauseHeader::ExceptHandler(item), + dangling_comments, + &format_with(|f| { + write!( + f, + [ + text("except"), + match self.except_handler_kind { + ExceptHandlerKind::Regular => None, + ExceptHandlerKind::Starred => Some(text("*")), + } + ] + )?; - if let Some(type_) = type_ { - write!( - f, - [ - space(), - maybe_parenthesize_expression(type_, item, Parenthesize::IfBreaks) - ] - )?; - if let Some(name) = name { - write!(f, [space(), text("as"), space(), name.format()])?; - } - } - write!( - f, - [ - text(":"), - trailing_comments(dangling_comments), - block_indent(&body.format()), + if let Some(type_) = type_ { + write!( + f, + [ + space(), + maybe_parenthesize_expression( + type_, + item, + Parenthesize::IfBreaks + ) + ] + )?; + if let Some(name) = name { + write!(f, [space(), text("as"), space(), name.format()])?; + } + } + + Ok(()) + }), + ), + clause_body(body, dangling_comments), ] ) } fn fmt_dangling_comments( &self, - _node: &ExceptHandlerExceptHandler, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { // dangling comments are formatted as part of fmt_fields diff --git a/crates/ruff_python_formatter/src/other/match_case.rs b/crates/ruff_python_formatter/src/other/match_case.rs index 91a584657ec2e..89c21bffa71eb 100644 --- a/crates/ruff_python_formatter/src/other/match_case.rs +++ b/crates/ruff_python_formatter/src/other/match_case.rs @@ -1,12 +1,81 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AstNode; use ruff_python_ast::MatchCase; +use crate::builders::parenthesize_if_expands; +use crate::comments::SourceComment; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses}; +use crate::prelude::*; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; +use crate::{FormatNodeRule, PyFormatter}; + #[derive(Default)] pub struct FormatMatchCase; impl FormatNodeRule for FormatMatchCase { fn fmt_fields(&self, item: &MatchCase, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let MatchCase { + range: _, + pattern, + guard, + body, + } = item; + + let comments = f.context().comments().clone(); + let dangling_item_comments = comments.dangling(item); + + write!( + f, + [ + clause_header( + ClauseHeader::MatchCase(item), + dangling_item_comments, + &format_with(|f| { + write!(f, [text("case"), space()])?; + + let has_comments = comments.has_leading(pattern) + || comments.has_trailing_own_line(pattern); + + if has_comments { + pattern.format().with_options(Parentheses::Always).fmt(f)?; + } else { + match pattern.needs_parentheses(item.as_any_node_ref(), f.context()) { + OptionalParentheses::Multiline => { + parenthesize_if_expands( + &pattern.format().with_options(Parentheses::Never), + ) + .fmt(f)?; + } + OptionalParentheses::Always => { + pattern.format().with_options(Parentheses::Always).fmt(f)?; + } + OptionalParentheses::Never => { + pattern.format().with_options(Parentheses::Never).fmt(f)?; + } + OptionalParentheses::BestFit => { + pattern.format().with_options(Parentheses::Never).fmt(f)?; + } + } + } + + if let Some(guard) = guard { + write!(f, [space(), text("if"), space(), guard.format()])?; + } + + Ok(()) + }), + ), + clause_body(body, dangling_item_comments), + ] + ) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/other/mod.rs b/crates/ruff_python_formatter/src/other/mod.rs index aedd4c6872fd1..e7eb28ae7f4fd 100644 --- a/crates/ruff_python_formatter/src/other/mod.rs +++ b/crates/ruff_python_formatter/src/other/mod.rs @@ -1,7 +1,6 @@ pub(crate) mod alias; -pub(crate) mod arg; -pub(crate) mod arg_with_default; pub(crate) mod arguments; +pub(crate) mod commas; pub(crate) mod comprehension; pub(crate) mod decorator; pub(crate) mod elif_else_clause; @@ -9,4 +8,7 @@ pub(crate) mod except_handler_except_handler; pub(crate) mod identifier; pub(crate) mod keyword; pub(crate) mod match_case; +pub(crate) mod parameter; +pub(crate) mod parameter_with_default; +pub(crate) mod parameters; pub(crate) mod with_item; diff --git a/crates/ruff_python_formatter/src/other/arg.rs b/crates/ruff_python_formatter/src/other/parameter.rs similarity index 53% rename from crates/ruff_python_formatter/src/other/arg.rs rename to crates/ruff_python_formatter/src/other/parameter.rs index 934a24a69b73d..dbbbfd8d617b3 100644 --- a/crates/ruff_python_formatter/src/other/arg.rs +++ b/crates/ruff_python_formatter/src/other/parameter.rs @@ -1,20 +1,20 @@ use crate::prelude::*; use crate::FormatNodeRule; use ruff_formatter::write; -use ruff_python_ast::Arg; +use ruff_python_ast::Parameter; #[derive(Default)] -pub struct FormatArg; +pub struct FormatParameter; -impl FormatNodeRule for FormatArg { - fn fmt_fields(&self, item: &Arg, f: &mut PyFormatter) -> FormatResult<()> { - let Arg { +impl FormatNodeRule for FormatParameter { + fn fmt_fields(&self, item: &Parameter, f: &mut PyFormatter) -> FormatResult<()> { + let Parameter { range: _, - arg, + name, annotation, } = item; - arg.format().fmt(f)?; + name.format().fmt(f)?; if let Some(annotation) = annotation { write!(f, [text(":"), space(), annotation.format()])?; diff --git a/crates/ruff_python_formatter/src/other/parameter_with_default.rs b/crates/ruff_python_formatter/src/other/parameter_with_default.rs new file mode 100644 index 0000000000000..3a5e6022ca862 --- /dev/null +++ b/crates/ruff_python_formatter/src/other/parameter_with_default.rs @@ -0,0 +1,27 @@ +use ruff_formatter::write; +use ruff_python_ast::ParameterWithDefault; + +use crate::prelude::*; +use crate::FormatNodeRule; + +#[derive(Default)] +pub struct FormatParameterWithDefault; + +impl FormatNodeRule for FormatParameterWithDefault { + fn fmt_fields(&self, item: &ParameterWithDefault, f: &mut PyFormatter) -> FormatResult<()> { + let ParameterWithDefault { + range: _, + parameter, + default, + } = item; + + write!(f, [parameter.format()])?; + + if let Some(default) = default { + let space = parameter.annotation.is_some().then_some(space()); + write!(f, [space, text("="), space, group(&default.format())])?; + } + + Ok(()) + } +} diff --git a/crates/ruff_python_formatter/src/other/parameters.rs b/crates/ruff_python_formatter/src/other/parameters.rs new file mode 100644 index 0000000000000..c7efcd4dc30d2 --- /dev/null +++ b/crates/ruff_python_formatter/src/other/parameters.rs @@ -0,0 +1,678 @@ +use std::usize; + +use ruff_formatter::{format_args, write, FormatRuleWithOptions}; +use ruff_python_ast::node::{AnyNodeRef, AstNode}; +use ruff_python_ast::{Parameters, Ranged}; +use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::{TextRange, TextSize}; + +use crate::comments::{ + dangling_comments, dangling_open_parenthesis_comments, leading_comments, leading_node_comments, + trailing_comments, CommentLinePosition, SourceComment, +}; +use crate::context::{NodeLevel, WithNodeLevel}; +use crate::expression::parentheses::empty_parenthesized; +use crate::prelude::*; +use crate::FormatNodeRule; + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] +pub enum ParametersParentheses { + /// By default, parameters will always preserve their surrounding parentheses. + #[default] + Preserve, + + /// Handle special cases where parentheses should never be used. + /// + /// An example where parentheses are never used for parameters would be with lambda + /// expressions. The following is invalid syntax: + /// ```python + /// lambda (x, y, z): ... + /// ``` + /// Instead the lambda here should be: + /// ```python + /// lambda x, y, z: ... + /// ``` + Never, +} + +#[derive(Default)] +pub struct FormatParameters { + parentheses: ParametersParentheses, +} + +impl FormatRuleWithOptions> for FormatParameters { + type Options = ParametersParentheses; + + fn with_options(mut self, options: Self::Options) -> Self { + self.parentheses = options; + self + } +} + +impl FormatNodeRule for FormatParameters { + fn fmt_fields(&self, item: &Parameters, f: &mut PyFormatter) -> FormatResult<()> { + let Parameters { + range: _, + posonlyargs, + args, + vararg, + kwonlyargs, + kwarg, + } = item; + + let (slash, star) = find_parameter_separators(f.context().source(), item); + + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + // First dangling comment: trailing the opening parenthesis, e.g.: + // ```python + // def f( # comment + // x, + // y, + // z, + // ): ... + // TODO(charlie): We already identified this comment as such in placement.rs. Consider + // labeling it as such. See: https://github.com/astral-sh/ruff/issues/5247. + let parenthesis_comments_end = usize::from(dangling.first().is_some_and(|comment| { + if comment.line_position().is_end_of_line() { + // Ensure that there are no tokens between the open bracket and the comment. + let mut lexer = SimpleTokenizer::new( + f.context().source(), + TextRange::new(item.start(), comment.start()), + ) + .skip_trivia() + .skip_while(|t| { + matches!( + t.kind(), + SimpleTokenKind::LParen + | SimpleTokenKind::LBrace + | SimpleTokenKind::LBracket + ) + }); + if lexer.next().is_none() { + return true; + } + } + false + })); + + // Separate into (dangling comments on the open parenthesis) and (dangling comments on the + // argument separators, e.g., `*` or `/`). + let (parenthesis_dangling, parameters_dangling) = + dangling.split_at(parenthesis_comments_end); + + let format_inner = format_with(|f: &mut PyFormatter| { + let separator = format_with(|f| write!(f, [text(","), soft_line_break_or_space()])); + let mut joiner = f.join_with(separator); + let mut last_node: Option = None; + + for parameter_with_default in posonlyargs { + joiner.entry(¶meter_with_default.format()); + + last_node = Some(parameter_with_default.into()); + } + + // Second dangling comment: trailing the slash, e.g.: + // ```python + // def f( + // x, + // /, # comment + // y, + // z, + // ): ... + let slash_comments_end = if posonlyargs.is_empty() { + 0 + } else { + let slash_comments_end = parameters_dangling.partition_point(|comment| { + let assignment = assign_argument_separator_comment_placement( + slash.as_ref(), + star.as_ref(), + comment.slice().range(), + comment.line_position(), + ) + .expect("Unexpected dangling comment type in function parameters"); + matches!( + assignment, + ArgumentSeparatorCommentLocation::SlashLeading + | ArgumentSeparatorCommentLocation::SlashTrailing + ) + }); + joiner.entry(&CommentsAroundText { + text: "/", + comments: ¶meters_dangling[..slash_comments_end], + }); + slash_comments_end + }; + + for parameter_with_default in args { + joiner.entry(¶meter_with_default.format()); + + last_node = Some(parameter_with_default.into()); + } + + // kw only args need either a `*args` ahead of them capturing all var args or a `*` + // pseudo-argument capturing all fields. We can also have `*args` without any kwargs + // afterwards. + if let Some(vararg) = vararg { + joiner.entry(&format_args![ + leading_node_comments(vararg.as_ref()), + text("*"), + vararg.format() + ]); + last_node = Some(vararg.as_any_node_ref()); + } else if !kwonlyargs.is_empty() { + // Given very strange comment placement, comments here may not actually have been + // marked as `StarLeading`/`StarTrailing`, but that's fine since we still produce + // a stable formatting in this case + // ```python + // def f42( + // a, + // / # 1 + // # 2 + // , # 3 + // # 4 + // * # 5 + // , # 6 + // c, + // ): + // pass + // ``` + joiner.entry(&CommentsAroundText { + text: "*", + comments: ¶meters_dangling[slash_comments_end..], + }); + } + + for parameter_with_default in kwonlyargs { + joiner.entry(¶meter_with_default.format()); + + last_node = Some(parameter_with_default.into()); + } + + if let Some(kwarg) = kwarg { + joiner.entry(&format_args![ + leading_node_comments(kwarg.as_ref()), + text("**"), + kwarg.format() + ]); + last_node = Some(kwarg.as_any_node_ref()); + } + + joiner.finish()?; + + // Functions use the regular magic trailing comma logic, lambdas may or may not have + // a trailing comma but it's just preserved without any magic. + // ```python + // # Add magic trailing comma if its expands + // def f(a): pass + // # Expands if magic trailing comma setting is respect, otherwise remove the comma + // def g(a,): pass + // # Never expands + // x1 = lambda y: 1 + // # Never expands, the comma is always preserved + // x2 = lambda y,: 1 + // ``` + if self.parentheses == ParametersParentheses::Never { + // For lambdas (no parentheses), preserve the trailing comma. It doesn't + // behave like a magic trailing comma, it's just preserved + if has_trailing_comma(item, last_node, f.context().source()) { + write!(f, [text(",")])?; + } + } else { + write!(f, [if_group_breaks(&text(","))])?; + + if f.options().magic_trailing_comma().is_respect() + && has_trailing_comma(item, last_node, f.context().source()) + { + // Make the magic trailing comma expand the group + write!(f, [hard_line_break()])?; + } + } + + Ok(()) + }); + + let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f); + + let num_parameters = posonlyargs.len() + + args.len() + + usize::from(vararg.is_some()) + + kwonlyargs.len() + + usize::from(kwarg.is_some()); + + if self.parentheses == ParametersParentheses::Never { + write!(f, [group(&format_inner), dangling_comments(dangling)]) + } else if num_parameters == 0 { + // No parameters, format any dangling comments between `()` + write!(f, [empty_parenthesized("(", dangling, ")")]) + } else { + // Intentionally avoid `parenthesized`, which groups the entire formatted contents. + // We want parameters to be grouped alongside return types, one level up, so we + // format them "inline" here. + write!( + f, + [ + text("("), + dangling_open_parenthesis_comments(parenthesis_dangling), + soft_block_indent(&group(&format_inner)), + text(")") + ] + ) + } + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) + } +} + +struct CommentsAroundText<'a> { + text: &'static str, + comments: &'a [SourceComment], +} + +impl Format> for CommentsAroundText<'_> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + if self.comments.is_empty() { + text(self.text).fmt(f) + } else { + // There might be own line comments in trailing, but those are weird and we can kinda + // ignore them + // ```python + // def f42( + // a, + // # leading comment (own line) + // / # first trailing comment (end-of-line) + // # trailing own line comment + // , + // c, + // ): + // ``` + let (leading, trailing) = self.comments.split_at( + self.comments + .partition_point(|comment| comment.line_position().is_own_line()), + ); + write!( + f, + [ + leading_comments(leading), + text(self.text), + trailing_comments(trailing) + ] + ) + } + } +} + +/// `/` and `*` in a function signature +/// +/// ```text +/// def f(arg_a, /, arg_b, *, arg_c): pass +/// ^ ^ ^ ^ ^ ^ slash preceding end +/// ^ ^ ^ ^ ^ slash (a separator) +/// ^ ^ ^ ^ slash following start +/// ^ ^ ^ star preceding end +/// ^ ^ star (a separator) +/// ^ star following start +/// ``` +#[derive(Debug)] +pub(crate) struct ParameterSeparator { + /// The end of the last node or separator before this separator + pub(crate) preceding_end: TextSize, + /// The range of the separator itself + pub(crate) separator: TextRange, + /// The start of the first node or separator following this separator + pub(crate) following_start: TextSize, +} + +/// Finds slash and star in `f(a, /, b, *, c)` or `lambda a, /, b, *, c: 1`. +/// +/// Returns the location of the slash and star separators, if any. +pub(crate) fn find_parameter_separators( + contents: &str, + parameters: &Parameters, +) -> (Option, Option) { + // We only compute preceding_end and token location here since following_start depends on the + // star location, but the star location depends on slash's position + let slash = if let Some(preceding_end) = parameters.posonlyargs.last().map(Ranged::end) { + // ```text + // def f(a1=1, a2=2, /, a3, a4): pass + // ^^^^^^^^^^^ the range (defaults) + // def f(a1, a2, /, a3, a4): pass + // ^^^^^^^^^^^^ the range (no default) + // ``` + let range = TextRange::new(preceding_end, parameters.end()); + let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia(); + + let comma = tokens + .next() + .expect("The function definition can't end here"); + debug_assert!(comma.kind() == SimpleTokenKind::Comma, "{comma:?}"); + let slash = tokens + .next() + .expect("The function definition can't end here"); + debug_assert!(slash.kind() == SimpleTokenKind::Slash, "{slash:?}"); + + Some((preceding_end, slash.range)) + } else { + None + }; + + // If we have a vararg we have a node that the comments attach to + let star = if parameters.vararg.is_some() { + // When the vararg is present the comments attach there and we don't need to do manual + // formatting + None + } else if let Some(first_keyword_argument) = parameters.kwonlyargs.first() { + // Check in that order: + // * `f(a, /, b, *, c)` and `f(a=1, /, b=2, *, c)` + // * `f(a, /, *, b)` + // * `f(*, b)` (else branch) + let after_parameters = parameters + .args + .last() + .map(|arg| arg.range.end()) + .or(slash.map(|(_, slash)| slash.end())); + if let Some(preceding_end) = after_parameters { + let range = TextRange::new(preceding_end, parameters.end()); + let mut tokens = SimpleTokenizer::new(contents, range).skip_trivia(); + + let comma = tokens + .next() + .expect("The function definition can't end here"); + debug_assert!(comma.kind() == SimpleTokenKind::Comma, "{comma:?}"); + let star = tokens + .next() + .expect("The function definition can't end here"); + debug_assert!(star.kind() == SimpleTokenKind::Star, "{star:?}"); + + Some(ParameterSeparator { + preceding_end, + separator: star.range, + following_start: first_keyword_argument.start(), + }) + } else { + let mut tokens = SimpleTokenizer::new(contents, parameters.range).skip_trivia(); + + let lparen_or_star = tokens + .next() + .expect("The function definition can't end here"); + + // In a function definition, the first token should always be a `(`; in a lambda + // definition, it _can't_ be a `(`. + let star = if lparen_or_star.kind == SimpleTokenKind::LParen { + tokens + .next() + .expect("The function definition can't end here") + } else { + lparen_or_star + }; + debug_assert!(star.kind() == SimpleTokenKind::Star, "{star:?}"); + + Some(ParameterSeparator { + preceding_end: parameters.start(), + separator: star.range, + following_start: first_keyword_argument.start(), + }) + } + } else { + None + }; + + // Now that we have star, compute how long slash trailing comments can go + // Check in that order: + // * `f(a, /, b)` + // * `f(a, /, *b)` + // * `f(a, /, *, b)` + // * `f(a, /)` + let slash_following_start = parameters + .args + .first() + .map(Ranged::start) + .or(parameters.vararg.as_ref().map(|first| first.start())) + .or(star.as_ref().map(|star| star.separator.start())) + .unwrap_or(parameters.end()); + let slash = slash.map(|(preceding_end, slash)| ParameterSeparator { + preceding_end, + separator: slash, + following_start: slash_following_start, + }); + + (slash, star) +} + +/// Locates positional only parameters separator `/` or the keywords only parameters +/// separator `*` comments. +/// +/// ```python +/// def test( +/// a, +/// # Positional only parameters after here +/// /, # trailing positional argument comment. +/// b, +/// ): +/// pass +/// ``` +/// or +/// ```python +/// def f( +/// a="", +/// # Keyword only parameters only after here +/// *, # trailing keyword argument comment. +/// b="", +/// ): +/// pass +/// ``` +/// or +/// ```python +/// def f( +/// a, +/// # positional only comment, leading +/// /, # positional only comment, trailing +/// b, +/// # keyword only comment, leading +/// *, # keyword only comment, trailing +/// c, +/// ): +/// pass +/// ``` +/// Notably, the following is possible: +/// ```python +/// def f32( +/// a, +/// # positional only comment, leading +/// /, # positional only comment, trailing +/// # keyword only comment, leading +/// *, # keyword only comment, trailing +/// c, +/// ): +/// pass +/// ``` +/// +/// ## Background +/// +/// ```text +/// def f(a1, a2): pass +/// ^^^^^^ parameters (args) +/// ``` +/// Use a star to separate keyword only parameters: +/// ```text +/// def f(a1, a2, *, a3, a4): pass +/// ^^^^^^ parameters (args) +/// ^^^^^^ keyword only parameters (kwargs) +/// ``` +/// Use a slash to separate positional only parameters. Note that this changes the parameters left +/// of the slash while the star change the parameters right of it: +/// ```text +/// def f(a1, a2, /, a3, a4): pass +/// ^^^^^^ positional only parameters (posonlyargs) +/// ^^^^^^ parameters (args) +/// ``` +/// You can combine both: +/// ```text +/// def f(a1, a2, /, a3, a4, *, a5, a6): pass +/// ^^^^^^ positional only parameters (posonlyargs) +/// ^^^^^^ parameters (args) +/// ^^^^^^ keyword only parameters (kwargs) +/// ``` +/// They can all have defaults, meaning that the preceding node ends at the default instead of the +/// argument itself: +/// ```text +/// def f(a1=1, a2=2, /, a3=3, a4=4, *, a5=5, a6=6): pass +/// ^ ^ ^ ^ ^ ^ defaults +/// ^^^^^^^^^^ positional only parameters (posonlyargs) +/// ^^^^^^^^^^ parameters (args) +/// ^^^^^^^^^^ keyword only parameters (kwargs) +/// ``` +/// An especially difficult case is having no regular parameters, so comments from both slash and +/// star will attach to either a2 or a3 and the next token is incorrect. +/// ```text +/// def f(a1, a2, /, *, a3, a4): pass +/// ^^^^^^ positional only parameters (posonlyargs) +/// ^^^^^^ keyword only parameters (kwargs) +/// ``` +pub(crate) fn assign_argument_separator_comment_placement( + slash: Option<&ParameterSeparator>, + star: Option<&ParameterSeparator>, + comment_range: TextRange, + text_position: CommentLinePosition, +) -> Option { + if let Some(ParameterSeparator { + preceding_end, + separator: slash, + following_start, + }) = slash + { + // ```python + // def f( + // # start too early + // a, # not own line + // # this is the one + // /, # too late (handled later) + // b, + // ) + // ``` + if comment_range.start() > *preceding_end + && comment_range.start() < slash.start() + && text_position.is_own_line() + { + return Some(ArgumentSeparatorCommentLocation::SlashLeading); + } + + // ```python + // def f( + // a, + // # too early (handled above) + // /, # this is the one + // # not end-of-line + // b, + // ) + // ``` + if comment_range.start() > slash.end() + && comment_range.start() < *following_start + && text_position.is_end_of_line() + { + return Some(ArgumentSeparatorCommentLocation::SlashTrailing); + } + } + + if let Some(ParameterSeparator { + preceding_end, + separator: star, + following_start, + }) = star + { + // ```python + // def f( + // # start too early + // a, # not own line + // # this is the one + // *, # too late (handled later) + // b, + // ) + // ``` + if comment_range.start() > *preceding_end + && comment_range.start() < star.start() + && text_position.is_own_line() + { + return Some(ArgumentSeparatorCommentLocation::StarLeading); + } + + // ```python + // def f( + // a, + // # too early (handled above) + // *, # this is the one + // # not end-of-line + // b, + // ) + // ``` + if comment_range.start() > star.end() + && comment_range.start() < *following_start + && text_position.is_end_of_line() + { + return Some(ArgumentSeparatorCommentLocation::StarTrailing); + } + } + None +} + +/// ```python +/// def f( +/// a, +/// # before slash +/// /, # after slash +/// b, +/// # before star +/// *, # after star +/// c, +/// ): +/// pass +/// ``` +#[derive(Debug)] +pub(crate) enum ArgumentSeparatorCommentLocation { + SlashLeading, + SlashTrailing, + StarLeading, + StarTrailing, +} + +fn has_trailing_comma( + parameters: &Parameters, + last_node: Option, + source: &str, +) -> bool { + // No nodes, no trailing comma + let Some(last_node) = last_node else { + return false; + }; + + let ends_with_pos_only_argument_separator = !parameters.posonlyargs.is_empty() + && parameters.args.is_empty() + && parameters.vararg.is_none() + && parameters.kwonlyargs.is_empty() + && parameters.kwarg.is_none(); + + let mut tokens = SimpleTokenizer::starts_at(last_node.end(), source).skip_trivia(); + // `def a(b, c, /): ... ` + // The slash lacks its own node + if ends_with_pos_only_argument_separator { + let comma = tokens.next(); + assert!(matches!(comma, Some(SimpleToken { kind: SimpleTokenKind::Comma, .. })), "The last positional only argument must be separated by a `,` from the positional only parameters separator `/` but found '{comma:?}'."); + + let slash = tokens.next(); + assert!(matches!(slash, Some(SimpleToken { kind: SimpleTokenKind::Slash, .. })), "The positional argument separator must be present for a function that has positional only parameters but found '{slash:?}'."); + } + + tokens + .next() + .expect("There must be a token after the argument list") + .kind() + == SimpleTokenKind::Comma +} diff --git a/crates/ruff_python_formatter/src/other/with_item.rs b/crates/ruff_python_formatter/src/other/with_item.rs index 49fd36393a007..3d8e373636923 100644 --- a/crates/ruff_python_formatter/src/other/with_item.rs +++ b/crates/ruff_python_formatter/src/other/with_item.rs @@ -1,10 +1,9 @@ -use ruff_python_ast::WithItem; - use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::WithItem; -use crate::comments::{leading_comments, trailing_comments}; +use crate::comments::SourceComment; use crate::expression::maybe_parenthesize_expression; -use crate::expression::parentheses::Parenthesize; +use crate::expression::parentheses::{parenthesized, Parentheses, Parenthesize}; use crate::prelude::*; use crate::{FormatNodeRule, PyFormatter}; @@ -20,34 +19,43 @@ impl FormatNodeRule for FormatWithItem { } = item; let comments = f.context().comments().clone(); - let trailing_as_comments = comments.dangling_comments(item); + let trailing_as_comments = comments.dangling(item); - maybe_parenthesize_expression(context_expr, item, Parenthesize::IfRequired).fmt(f)?; + write!( + f, + [maybe_parenthesize_expression( + context_expr, + item, + Parenthesize::IfRequired + )] + )?; if let Some(optional_vars) = optional_vars { - write!( - f, - [space(), text("as"), trailing_comments(trailing_as_comments)] - )?; - let leading_var_comments = comments.leading_comments(optional_vars.as_ref()); - if leading_var_comments.is_empty() { - write!(f, [space(), optional_vars.format()])?; + write!(f, [space(), text("as"), space()])?; + + if trailing_as_comments.is_empty() { + write!(f, [optional_vars.format()])?; } else { write!( f, - [ - // Otherwise the comment would end up on the same line as the `as` - hard_line_break(), - leading_comments(leading_var_comments), - optional_vars.format() - ] + [parenthesized( + "(", + &optional_vars.format().with_options(Parentheses::Never), + ")", + ) + .with_dangling_comments(trailing_as_comments)] )?; } } + Ok(()) } - fn fmt_dangling_comments(&self, _node: &WithItem, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { Ok(()) } } diff --git a/crates/ruff_python_formatter/src/pattern/mod.rs b/crates/ruff_python_formatter/src/pattern/mod.rs index 992f90a49da18..35c6eca1e68ca 100644 --- a/crates/ruff_python_formatter/src/pattern/mod.rs +++ b/crates/ruff_python_formatter/src/pattern/mod.rs @@ -1,3 +1,13 @@ +use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{Pattern, Ranged}; +use ruff_python_trivia::{first_non_trivia_token, SimpleToken, SimpleTokenKind, SimpleTokenizer}; + +use crate::expression::parentheses::{ + parenthesized, NeedsParentheses, OptionalParentheses, Parentheses, +}; +use crate::prelude::*; + pub(crate) mod pattern_match_as; pub(crate) mod pattern_match_class; pub(crate) mod pattern_match_mapping; @@ -6,3 +16,124 @@ pub(crate) mod pattern_match_sequence; pub(crate) mod pattern_match_singleton; pub(crate) mod pattern_match_star; pub(crate) mod pattern_match_value; + +#[derive(Copy, Clone, PartialEq, Eq, Default)] +pub struct FormatPattern { + parentheses: Parentheses, +} + +impl FormatRuleWithOptions> for FormatPattern { + type Options = Parentheses; + + fn with_options(mut self, options: Self::Options) -> Self { + self.parentheses = options; + self + } +} + +impl FormatRule> for FormatPattern { + fn fmt(&self, pattern: &Pattern, f: &mut PyFormatter) -> FormatResult<()> { + let format_pattern = format_with(|f| match pattern { + Pattern::MatchValue(pattern) => pattern.format().fmt(f), + Pattern::MatchSingleton(pattern) => pattern.format().fmt(f), + Pattern::MatchSequence(pattern) => pattern.format().fmt(f), + Pattern::MatchMapping(pattern) => pattern.format().fmt(f), + Pattern::MatchClass(pattern) => pattern.format().fmt(f), + Pattern::MatchStar(pattern) => pattern.format().fmt(f), + Pattern::MatchAs(pattern) => pattern.format().fmt(f), + Pattern::MatchOr(pattern) => pattern.format().fmt(f), + }); + + let parenthesize = match self.parentheses { + Parentheses::Preserve => is_pattern_parenthesized(pattern, f.context().source()), + Parentheses::Always => true, + Parentheses::Never => false, + }; + + if parenthesize { + let comments = f.context().comments().clone(); + + // Any comments on the open parenthesis. + // + // For example, `# comment` in: + // ```python + // ( # comment + // 1 + // ) + // ``` + let open_parenthesis_comment = comments + .leading(pattern) + .first() + .filter(|comment| comment.line_position().is_end_of_line()); + + parenthesized("(", &format_pattern, ")") + .with_dangling_comments( + open_parenthesis_comment + .map(std::slice::from_ref) + .unwrap_or_default(), + ) + .fmt(f) + } else { + format_pattern.fmt(f) + } + } +} + +impl<'ast> AsFormat> for Pattern { + type Format<'a> = FormatRefWithRule<'a, Pattern, FormatPattern, PyFormatContext<'ast>>; + + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new(self, FormatPattern::default()) + } +} + +impl<'ast> IntoFormat> for Pattern { + type Format = FormatOwnedWithRule>; + + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new(self, FormatPattern::default()) + } +} + +fn is_pattern_parenthesized(pattern: &Pattern, contents: &str) -> bool { + // First test if there's a closing parentheses because it tends to be cheaper. + if matches!( + first_non_trivia_token(pattern.end(), contents), + Some(SimpleToken { + kind: SimpleTokenKind::RParen, + .. + }) + ) { + let mut tokenizer = + SimpleTokenizer::up_to_without_back_comment(pattern.start(), contents).skip_trivia(); + + matches!( + tokenizer.next_back(), + Some(SimpleToken { + kind: SimpleTokenKind::LParen, + .. + }) + ) + } else { + false + } +} + +impl NeedsParentheses for Pattern { + fn needs_parentheses( + &self, + parent: AnyNodeRef, + context: &PyFormatContext, + ) -> OptionalParentheses { + match self { + Pattern::MatchValue(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchSingleton(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchSequence(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchMapping(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchClass(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchStar(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchAs(pattern) => pattern.needs_parentheses(parent, context), + Pattern::MatchOr(pattern) => pattern.needs_parentheses(parent, context), + } + } +} diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs index efe8364e24cb2..c6dc298e3e630 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs @@ -1,12 +1,70 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchAs; +use crate::comments::{dangling_comments, SourceComment}; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::prelude::*; +use crate::{FormatNodeRule, PyFormatter}; + #[derive(Default)] pub struct FormatPatternMatchAs; impl FormatNodeRule for FormatPatternMatchAs { fn fmt_fields(&self, item: &PatternMatchAs, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let PatternMatchAs { + range: _, + pattern, + name, + } = item; + + let comments = f.context().comments().clone(); + + if let Some(name) = name { + if let Some(pattern) = pattern { + pattern.format().fmt(f)?; + + if comments.has_trailing(pattern.as_ref()) { + write!(f, [hard_line_break()])?; + } else { + write!(f, [space()])?; + } + + write!(f, [text("as")])?; + + let trailing_as_comments = comments.dangling(item); + if trailing_as_comments.is_empty() { + write!(f, [space()])?; + } else if trailing_as_comments + .iter() + .all(|comment| comment.line_position().is_own_line()) + { + write!(f, [hard_line_break()])?; + } + write!(f, [dangling_comments(trailing_as_comments)])?; + } + name.format().fmt(f) + } else { + debug_assert!(pattern.is_none()); + text("_").fmt(f) + } + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + Ok(()) + } +} + +impl NeedsParentheses for PatternMatchAs { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Multiline } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs index 4aeb063da44d6..84d11384e05ed 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs @@ -1,12 +1,32 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchClass; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::prelude::*; +use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; + #[derive(Default)] pub struct FormatPatternMatchClass; impl FormatNodeRule for FormatPatternMatchClass { fn fmt_fields(&self, item: &PatternMatchClass, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + write!( + f, + [not_yet_implemented_custom_text( + "NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0)", + item + )] + ) + } +} + +impl NeedsParentheses for PatternMatchClass { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs index ea629eb9d97ec..ab722e4eb3281 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs @@ -1,12 +1,187 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_formatter::{format_args, write}; +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchMapping; +use ruff_python_ast::{Expr, Identifier, Pattern, Ranged}; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::TextRange; + +use crate::comments::{leading_comments, trailing_comments, SourceComment}; +use crate::expression::parentheses::{ + empty_parenthesized, parenthesized, NeedsParentheses, OptionalParentheses, +}; +use crate::prelude::*; #[derive(Default)] pub struct FormatPatternMatchMapping; impl FormatNodeRule for FormatPatternMatchMapping { fn fmt_fields(&self, item: &PatternMatchMapping, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let PatternMatchMapping { + keys, + patterns, + rest, + range: _, + } = item; + + debug_assert_eq!(keys.len(), patterns.len()); + + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + if keys.is_empty() && rest.is_none() { + return empty_parenthesized("{", dangling, "}").fmt(f); + } + + // This node supports three kinds of dangling comments. Most of the complexity originates + // with the rest pattern (`{**rest}`), since we can have comments around the `**`, but + // also, the `**rest` itself is not a node (it's an identifier), so comments that trail it + // are _also_ dangling. + // + // Specifically, we have these three sources of dangling comments: + // ```python + // { # "open parenthesis comment" + // key: pattern, + // ** # end-of-line "double star comment" + // # own-line "double star comment" + // rest # end-of-line "after rest comment" + // # own-line "after rest comment" + // } + // ``` + let (open_parenthesis_comments, double_star_comments, after_rest_comments) = + if let Some((double_star, rest)) = find_double_star(item, f.context().source()) { + let (open_parenthesis_comments, dangling) = + dangling.split_at(dangling.partition_point(|comment| { + comment.line_position().is_end_of_line() + && comment.start() < double_star.start() + })); + let (double_star_comments, after_rest_comments) = dangling + .split_at(dangling.partition_point(|comment| comment.start() < rest.start())); + ( + open_parenthesis_comments, + double_star_comments, + after_rest_comments, + ) + } else { + (dangling, [].as_slice(), [].as_slice()) + }; + + let format_pairs = format_with(|f| { + let mut joiner = f.join_comma_separated(item.end()); + + for (key, pattern) in keys.iter().zip(patterns) { + let key_pattern_pair = KeyPatternPair { key, pattern }; + joiner.entry(&key_pattern_pair, &key_pattern_pair); + } + + if let Some(identifier) = rest { + let rest_pattern = RestPattern { + identifier, + comments: double_star_comments, + }; + joiner.entry(&rest_pattern, &rest_pattern); + } + + joiner.finish()?; + + trailing_comments(after_rest_comments).fmt(f) + }); + + parenthesized("{", &format_pairs, "}") + .with_dangling_comments(open_parenthesis_comments) + .fmt(f) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled by `fmt_fields` + Ok(()) } } + +impl NeedsParentheses for PatternMatchMapping { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never + } +} + +/// A struct to format the `rest` element of a [`PatternMatchMapping`] (e.g., `{**rest}`). +#[derive(Debug)] +struct RestPattern<'a> { + identifier: &'a Identifier, + comments: &'a [SourceComment], +} + +impl Ranged for RestPattern<'_> { + fn range(&self) -> TextRange { + self.identifier.range() + } +} + +impl Format> for RestPattern<'_> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + write!( + f, + [ + leading_comments(self.comments), + text("**"), + self.identifier.format() + ] + ) + } +} + +/// A struct to format a key-pattern pair of a [`PatternMatchMapping`] (e.g., `{key: pattern}`). +#[derive(Debug)] +struct KeyPatternPair<'a> { + key: &'a Expr, + pattern: &'a Pattern, +} + +impl Ranged for KeyPatternPair<'_> { + fn range(&self) -> TextRange { + TextRange::new(self.key.start(), self.pattern.end()) + } +} + +impl Format> for KeyPatternPair<'_> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + write!( + f, + [group(&format_args![ + self.key.format(), + text(":"), + space(), + self.pattern.format() + ])] + ) + } +} + +/// Given a [`PatternMatchMapping`], finds the range of the `**` element in the `rest` pattern, +/// if it exists. +fn find_double_star(pattern: &PatternMatchMapping, source: &str) -> Option<(TextRange, TextRange)> { + let PatternMatchMapping { + keys: _, + patterns, + rest, + range: _, + } = pattern; + + // If there's no `rest` element, there's no `**`. + let Some(rest) = rest else { + return None; + }; + + let mut tokenizer = + SimpleTokenizer::starts_at(patterns.last().map_or(pattern.start(), Ranged::end), source); + let double_star = tokenizer.find(|token| token.kind() == SimpleTokenKind::DoubleStar)?; + + Some((double_star.range(), rest.range())) +} diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs index be809d2056799..6d7e624ae8625 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs @@ -1,12 +1,32 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchOr; +use crate::context::PyFormatContext; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; + #[derive(Default)] pub struct FormatPatternMatchOr; impl FormatNodeRule for FormatPatternMatchOr { fn fmt_fields(&self, item: &PatternMatchOr, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + write!( + f, + [not_yet_implemented_custom_text( + "NOT_YET_IMPLEMENTED_PatternMatchOf | (y)", + item + )] + ) + } +} + +impl NeedsParentheses for PatternMatchOr { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Multiline } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs index 7f5a9390eb4d7..c9346c4e46d39 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs @@ -1,12 +1,124 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::PatternMatchSequence; +use ruff_formatter::prelude::format_with; +use ruff_formatter::{Format, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{PatternMatchSequence, Ranged}; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::TextRange; + +use crate::builders::PyFormatterExtensions; +use crate::context::PyFormatContext; +use crate::expression::parentheses::{ + empty_parenthesized, optional_parentheses, parenthesized, NeedsParentheses, OptionalParentheses, +}; +use crate::{FormatNodeRule, PyFormatter}; #[derive(Default)] pub struct FormatPatternMatchSequence; impl FormatNodeRule for FormatPatternMatchSequence { fn fmt_fields(&self, item: &PatternMatchSequence, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let PatternMatchSequence { patterns, range } = item; + + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + let sequence_type = SequenceType::from_pattern(item, f.context().source()); + if patterns.is_empty() { + return match sequence_type { + SequenceType::List => empty_parenthesized("[", dangling, "]").fmt(f), + SequenceType::Tuple | SequenceType::TupleNoParens => { + empty_parenthesized("(", dangling, ")").fmt(f) + } + }; + } + let items = format_with(|f| { + f.join_comma_separated(range.end()) + .nodes(patterns.iter()) + .finish() + }); + match sequence_type { + SequenceType::Tuple => parenthesized("(", &items, ")") + .with_dangling_comments(dangling) + .fmt(f), + SequenceType::List => parenthesized("[", &items, "]") + .with_dangling_comments(dangling) + .fmt(f), + SequenceType::TupleNoParens => optional_parentheses(&items).fmt(f), + } + } +} + +impl NeedsParentheses for PatternMatchSequence { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum SequenceType { + /// A list literal, e.g., `[1, 2, 3]`. + List, + /// A parenthesized tuple literal, e.g., `(1, 2, 3)`. + Tuple, + /// A tuple literal without parentheses, e.g., `1, 2, 3`. + TupleNoParens, +} + +impl SequenceType { + pub(crate) fn from_pattern(pattern: &PatternMatchSequence, source: &str) -> SequenceType { + if source[pattern.range()].starts_with('[') { + SequenceType::List + } else if source[pattern.range()].starts_with('(') { + // If the pattern is empty, it must be a parenthesized tuple with no members. (This + // branch exists to differentiate between a tuple with and without its own parentheses, + // but a tuple without its own parentheses must have at least one member.) + let Some(elt) = pattern.patterns.first() else { + return SequenceType::Tuple; + }; + + // Count the number of open parentheses between the start of the pattern and the first + // element, and the number of close parentheses between the first element and its + // trailing comma. If the number of open parentheses is greater than the number of close + // parentheses, + // the pattern is parenthesized. For example, here, we have two parentheses before the + // first element, and one after it: + // ```python + // ((a), b, c) + // ``` + // + // This algorithm successfully avoids false positives for cases like: + // ```python + // (a), b, c + // ``` + let open_parentheses_count = + SimpleTokenizer::new(source, TextRange::new(pattern.start(), elt.start())) + .skip_trivia() + .filter(|token| token.kind() == SimpleTokenKind::LParen) + .count(); + + // Count the number of close parentheses. + let close_parentheses_count = + SimpleTokenizer::new(source, TextRange::new(elt.end(), elt.end())) + .skip_trivia() + .take_while(|token| token.kind() != SimpleTokenKind::Comma) + .filter(|token| token.kind() == SimpleTokenKind::RParen) + .count(); + + if open_parentheses_count > close_parentheses_count { + SequenceType::Tuple + } else { + SequenceType::TupleNoParens + } + } else { + SequenceType::TupleNoParens + } + } + + pub(crate) fn is_parenthesized(self) -> bool { + matches!(self, SequenceType::List | SequenceType::Tuple) } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs index 0b06a2c56c98b..5017a9fa88da5 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs @@ -1,12 +1,30 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::PatternMatchSingleton; +use crate::prelude::*; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{Constant, PatternMatchSingleton}; + +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::{FormatNodeRule, PyFormatter}; #[derive(Default)] pub struct FormatPatternMatchSingleton; impl FormatNodeRule for FormatPatternMatchSingleton { fn fmt_fields(&self, item: &PatternMatchSingleton, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + match item.value { + Constant::None => text("None").fmt(f), + Constant::Bool(true) => text("True").fmt(f), + Constant::Bool(false) => text("False").fmt(f), + _ => unreachable!(), + } + } +} + +impl NeedsParentheses for PatternMatchSingleton { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs index d7b457078d5e3..35978eb386230 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs @@ -1,12 +1,45 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchStar; +use crate::comments::{dangling_comments, SourceComment}; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; +use crate::prelude::*; + #[derive(Default)] pub struct FormatPatternMatchStar; impl FormatNodeRule for FormatPatternMatchStar { fn fmt_fields(&self, item: &PatternMatchStar, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let PatternMatchStar { name, .. } = item; + + let comments = f.context().comments().clone(); + let dangling = comments.dangling(item); + + write!(f, [text("*"), dangling_comments(dangling)])?; + + match name { + Some(name) => write!(f, [name.format()]), + None => write!(f, [text("_")]), + } + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled by `fmt_fields` + Ok(()) + } +} + +impl NeedsParentheses for PatternMatchStar { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never } } diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs index 09d53faea4821..dc1b090b7a6d9 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs @@ -1,14 +1,26 @@ +use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::PatternMatchValue; -use ruff_formatter::{write, Buffer, FormatResult}; - -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; +use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses}; +use crate::prelude::*; +use crate::{AsFormat, FormatNodeRule, PyFormatter}; #[derive(Default)] pub struct FormatPatternMatchValue; impl FormatNodeRule for FormatPatternMatchValue { fn fmt_fields(&self, item: &PatternMatchValue, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let PatternMatchValue { value, range: _ } = item; + value.format().with_options(Parentheses::Never).fmt(f) + } +} + +impl NeedsParentheses for PatternMatchValue { + fn needs_parentheses( + &self, + _parent: AnyNodeRef, + _context: &PyFormatContext, + ) -> OptionalParentheses { + OptionalParentheses::Never } } diff --git a/crates/ruff_python_formatter/src/statement/clause.rs b/crates/ruff_python_formatter/src/statement/clause.rs new file mode 100644 index 0000000000000..81963ae0ca2c6 --- /dev/null +++ b/crates/ruff_python_formatter/src/statement/clause.rs @@ -0,0 +1,463 @@ +use crate::comments::{ + leading_alternate_branch_comments, trailing_comments, SourceComment, SuppressionKind, +}; +use crate::prelude::*; +use crate::statement::suite::{contains_only_an_ellipsis, SuiteKind}; +use crate::verbatim::write_suppressed_clause_header; +use ruff_formatter::{write, Argument, Arguments, FormatError}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{ + ElifElseClause, ExceptHandlerExceptHandler, MatchCase, Ranged, StmtClassDef, StmtFor, + StmtFunctionDef, StmtIf, StmtMatch, StmtTry, StmtWhile, StmtWith, Suite, +}; +use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::{TextRange, TextSize}; + +/// The header of a compound statement clause. +/// +/// > A compound statement consists of one or more ‘clauses.’ A clause consists of a header and a ‘suite.’ +/// > The clause headers of a particular compound statement are all at the same indentation level. +/// > Each clause header begins with a uniquely identifying keyword and ends with a colon. +/// [source](https://docs.python.org/3/reference/compound_stmts.html#compound-statements) +#[derive(Copy, Clone)] +pub(crate) enum ClauseHeader<'a> { + Class(&'a StmtClassDef), + Function(&'a StmtFunctionDef), + If(&'a StmtIf), + ElifElse(&'a ElifElseClause), + Try(&'a StmtTry), + ExceptHandler(&'a ExceptHandlerExceptHandler), + TryFinally(&'a StmtTry), + Match(&'a StmtMatch), + MatchCase(&'a MatchCase), + For(&'a StmtFor), + While(&'a StmtWhile), + With(&'a StmtWith), + OrElse(ElseClause<'a>), +} + +impl<'a> ClauseHeader<'a> { + /// The range from the clause keyword up to and including the final colon. + pub(crate) fn range(self, source: &str) -> FormatResult { + let keyword_range = self.first_keyword_range(source)?; + + let mut last_child_end = None; + + self.visit(&mut |child| last_child_end = Some(child.end())); + + let end = match self { + ClauseHeader::Class(class) => Some(last_child_end.unwrap_or(class.name.end())), + ClauseHeader::Function(function) => Some(last_child_end.unwrap_or(function.name.end())), + ClauseHeader::ElifElse(_) + | ClauseHeader::Try(_) + | ClauseHeader::If(_) + | ClauseHeader::TryFinally(_) + | ClauseHeader::Match(_) + | ClauseHeader::MatchCase(_) + | ClauseHeader::For(_) + | ClauseHeader::While(_) + | ClauseHeader::With(_) + | ClauseHeader::OrElse(_) => last_child_end, + + ClauseHeader::ExceptHandler(handler) => handler + .name + .as_ref() + .map(ruff_python_ast::Ranged::end) + .or(last_child_end), + }; + + let colon = colon_range(end.unwrap_or(keyword_range.end()), source)?; + + Ok(TextRange::new(keyword_range.start(), colon.end())) + } + + /// Visits the nodes in the case header. + pub(crate) fn visit(self, visitor: &mut F) + where + F: FnMut(AnyNodeRef), + { + fn visit<'a, N, F>(node: N, visitor: &mut F) + where + N: Into>, + F: FnMut(AnyNodeRef<'a>), + { + visitor(node.into()); + } + + match self { + ClauseHeader::Class(StmtClassDef { + type_params, + arguments, + range: _, + decorator_list: _, + name: _, + body: _, + }) => { + if let Some(type_params) = type_params.as_deref() { + visit(type_params, visitor); + } + + if let Some(arguments) = arguments { + visit(arguments.as_ref(), visitor); + } + } + ClauseHeader::Function(StmtFunctionDef { + type_params, + parameters, + range: _, + is_async: _, + decorator_list: _, + name: _, + returns, + body: _, + }) => { + if let Some(type_params) = type_params.as_ref() { + visit(type_params, visitor); + } + visit(parameters.as_ref(), visitor); + + if let Some(returns) = returns.as_deref() { + visit(returns, visitor); + } + } + ClauseHeader::If(StmtIf { + test, + range: _, + body: _, + elif_else_clauses: _, + }) => { + visit(test.as_ref(), visitor); + } + ClauseHeader::ElifElse(ElifElseClause { + test, + range: _, + body: _, + }) => { + if let Some(test) = test.as_ref() { + visit(test, visitor); + } + } + + ClauseHeader::ExceptHandler(ExceptHandlerExceptHandler { + type_: type_expr, + range: _, + name: _, + body: _, + }) => { + if let Some(type_expr) = type_expr.as_deref() { + visit(type_expr, visitor); + } + } + ClauseHeader::Match(StmtMatch { + subject, + range: _, + cases: _, + }) => { + visit(subject.as_ref(), visitor); + } + ClauseHeader::MatchCase(MatchCase { + guard, + pattern, + range: _, + body: _, + }) => { + visit(pattern, visitor); + + if let Some(guard) = guard.as_deref() { + visit(guard, visitor); + } + } + ClauseHeader::For(StmtFor { + target, + iter, + range: _, + is_async: _, + body: _, + orelse: _, + }) => { + visit(target.as_ref(), visitor); + visit(iter.as_ref(), visitor); + } + ClauseHeader::While(StmtWhile { + test, + range: _, + body: _, + orelse: _, + }) => { + visit(test.as_ref(), visitor); + } + ClauseHeader::With(StmtWith { + items, + range: _, + is_async: _, + body: _, + }) => { + for item in items { + visit(item, visitor); + } + } + ClauseHeader::Try(_) | ClauseHeader::TryFinally(_) | ClauseHeader::OrElse(_) => {} + } + } + + /// Returns the range of the first keyword that marks the start of the clause header. + fn first_keyword_range(self, source: &str) -> FormatResult { + match self { + ClauseHeader::Class(header) => { + find_keyword(header.start(), SimpleTokenKind::Class, source) + } + ClauseHeader::Function(header) => { + let keyword = if header.is_async { + SimpleTokenKind::Async + } else { + SimpleTokenKind::Def + }; + find_keyword(header.start(), keyword, source) + } + ClauseHeader::If(header) => find_keyword(header.start(), SimpleTokenKind::If, source), + ClauseHeader::ElifElse(ElifElseClause { + test: None, range, .. + }) => find_keyword(range.start(), SimpleTokenKind::Else, source), + ClauseHeader::ElifElse(ElifElseClause { + test: Some(_), + range, + .. + }) => find_keyword(range.start(), SimpleTokenKind::Elif, source), + ClauseHeader::Try(header) => find_keyword(header.start(), SimpleTokenKind::Try, source), + ClauseHeader::ExceptHandler(header) => { + find_keyword(header.start(), SimpleTokenKind::Except, source) + } + ClauseHeader::TryFinally(header) => { + let last_statement = header + .orelse + .last() + .map(AnyNodeRef::from) + .or_else(|| header.handlers.last().map(AnyNodeRef::from)) + .or_else(|| header.body.last().map(AnyNodeRef::from)) + .unwrap(); + + find_keyword(last_statement.end(), SimpleTokenKind::Finally, source) + } + ClauseHeader::Match(header) => { + find_keyword(header.start(), SimpleTokenKind::Match, source) + } + ClauseHeader::MatchCase(header) => { + find_keyword(header.start(), SimpleTokenKind::Case, source) + } + ClauseHeader::For(header) => { + let keyword = if header.is_async { + SimpleTokenKind::Async + } else { + SimpleTokenKind::For + }; + find_keyword(header.start(), keyword, source) + } + ClauseHeader::While(header) => { + find_keyword(header.start(), SimpleTokenKind::While, source) + } + ClauseHeader::With(header) => { + let keyword = if header.is_async { + SimpleTokenKind::Async + } else { + SimpleTokenKind::With + }; + + find_keyword(header.start(), keyword, source) + } + ClauseHeader::OrElse(header) => match header { + ElseClause::Try(try_stmt) => { + let last_statement = try_stmt + .handlers + .last() + .map(AnyNodeRef::from) + .or_else(|| try_stmt.body.last().map(AnyNodeRef::from)) + .unwrap(); + + find_keyword(last_statement.end(), SimpleTokenKind::Else, source) + } + ElseClause::For(StmtFor { body, .. }) + | ElseClause::While(StmtWhile { body, .. }) => { + find_keyword(body.last().unwrap().end(), SimpleTokenKind::Else, source) + } + }, + } + } +} + +#[derive(Copy, Clone)] +pub(crate) enum ElseClause<'a> { + Try(&'a StmtTry), + For(&'a StmtFor), + While(&'a StmtWhile), +} + +pub(crate) struct FormatClauseHeader<'a, 'ast> { + header: ClauseHeader<'a>, + /// How to format the clause header + formatter: Argument<'a, PyFormatContext<'ast>>, + + /// Leading comments coming before the branch, together with the previous node, if any. Only relevant + /// for alternate branches. + leading_comments: Option<(&'a [SourceComment], Option>)>, + + /// The trailing comments coming after the colon. + trailing_colon_comment: &'a [SourceComment], +} + +/// Formats a clause header, handling the case where the clause header is suppressed and should not be formatted. +/// +/// Calls the `formatter` to format the content of the `header`, except if the `trailing_colon_comment` is a `fmt: skip` suppression comment. +/// Takes care of formatting the `trailing_colon_comment` and adds the `:` at the end of the header. +pub(crate) fn clause_header<'a, 'ast, Content>( + header: ClauseHeader<'a>, + trailing_colon_comment: &'a [SourceComment], + formatter: &'a Content, +) -> FormatClauseHeader<'a, 'ast> +where + Content: Format>, +{ + FormatClauseHeader { + header, + formatter: Argument::new(formatter), + leading_comments: None, + trailing_colon_comment, + } +} + +impl<'a> FormatClauseHeader<'a, '_> { + /// Sets the leading comments that precede an alternate branch. + #[must_use] + pub(crate) fn with_leading_comments( + mut self, + comments: &'a [SourceComment], + last_node: Option, + ) -> Self + where + N: Into>, + { + self.leading_comments = Some((comments, last_node.map(Into::into))); + self + } +} + +impl<'ast> Format> for FormatClauseHeader<'_, 'ast> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + if let Some((leading_comments, last_node)) = self.leading_comments { + leading_alternate_branch_comments(leading_comments, last_node).fmt(f)?; + } + + if SuppressionKind::has_skip_comment(self.trailing_colon_comment, f.context().source()) { + write_suppressed_clause_header(self.header, f)?; + } else { + f.write_fmt(Arguments::from(&self.formatter))?; + text(":").fmt(f)?; + } + + trailing_comments(self.trailing_colon_comment).fmt(f) + } +} + +pub(crate) struct FormatClauseBody<'a> { + body: &'a Suite, + kind: SuiteKind, + trailing_comments: &'a [SourceComment], +} + +impl<'a> FormatClauseBody<'a> { + #[must_use] + pub(crate) fn with_kind(mut self, kind: SuiteKind) -> Self { + self.kind = kind; + self + } +} + +pub(crate) fn clause_body<'a>( + body: &'a Suite, + trailing_comments: &'a [SourceComment], +) -> FormatClauseBody<'a> { + FormatClauseBody { + body, + kind: SuiteKind::default(), + trailing_comments, + } +} + +impl Format> for FormatClauseBody<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + if f.options().source_type().is_stub() + && contains_only_an_ellipsis(self.body, f.context().comments()) + && self.trailing_comments.is_empty() + { + write!( + f, + [ + space(), + self.body.format().with_options(self.kind), + hard_line_break() + ] + ) + } else { + write!( + f, + [ + trailing_comments(self.trailing_comments), + block_indent(&self.body.format().with_options(self.kind)) + ] + ) + } + } +} + +/// Finds the range of `keyword` starting the search at `start_position`. Expects only comments and `(` between +/// the `start_position` and the `keyword` token. +fn find_keyword( + start_position: TextSize, + keyword: SimpleTokenKind, + source: &str, +) -> FormatResult { + let mut tokenizer = SimpleTokenizer::starts_at(start_position, source).skip_trivia(); + + match tokenizer.next() { + Some(token) if token.kind() == keyword => Ok(token.range()), + Some(other) => { + debug_assert!( + false, + "Expected the keyword token {keyword:?} but found the token {other:?} instead." + ); + Err(FormatError::syntax_error( + "Expected the keyword token but found another token instead.", + )) + } + None => { + debug_assert!( + false, + "Expected the keyword token {keyword:?} but reached the end of the source instead." + ); + Err(FormatError::syntax_error( + "Expected the case header keyword token but reached the end of the source instead.", + )) + } + } +} + +/// Returns the range of the `:` ending the clause header or `Err` if the colon can't be found. +fn colon_range(after_keyword_or_condition: TextSize, source: &str) -> FormatResult { + let mut tokenizer = SimpleTokenizer::starts_at(after_keyword_or_condition, source) + .skip_trivia() + .skip_while(|token| token.kind() == SimpleTokenKind::RParen); + + match tokenizer.next() { + Some(SimpleToken { + kind: SimpleTokenKind::Colon, + range, + }) => Ok(range), + Some(token) => { + debug_assert!(false, "Expected the colon marking the end of the case header but found {token:?} instead."); + Err(FormatError::syntax_error("Expected colon marking the end of the case header but found another token instead.")) + } + None => { + debug_assert!(false, "Expected the colon marking the end of the case header but found the end of the range."); + Err(FormatError::syntax_error("Expected the colon marking the end of the case header but found the end of the range.")) + } + } +} diff --git a/crates/ruff_python_formatter/src/statement/mod.rs b/crates/ruff_python_formatter/src/statement/mod.rs index ed03b4b2c3018..7bc0a4c27ff12 100644 --- a/crates/ruff_python_formatter/src/statement/mod.rs +++ b/crates/ruff_python_formatter/src/statement/mod.rs @@ -1,13 +1,12 @@ -use crate::prelude::*; use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule}; use ruff_python_ast::Stmt; +use crate::prelude::*; + +pub(super) mod clause; pub(crate) mod stmt_ann_assign; pub(crate) mod stmt_assert; pub(crate) mod stmt_assign; -pub(crate) mod stmt_async_for; -pub(crate) mod stmt_async_function_def; -pub(crate) mod stmt_async_with; pub(crate) mod stmt_aug_assign; pub(crate) mod stmt_break; pub(crate) mod stmt_class_def; @@ -20,13 +19,13 @@ pub(crate) mod stmt_global; pub(crate) mod stmt_if; pub(crate) mod stmt_import; pub(crate) mod stmt_import_from; +pub(crate) mod stmt_ipy_escape_command; pub(crate) mod stmt_match; pub(crate) mod stmt_nonlocal; pub(crate) mod stmt_pass; pub(crate) mod stmt_raise; pub(crate) mod stmt_return; pub(crate) mod stmt_try; -pub(crate) mod stmt_try_star; pub(crate) mod stmt_type_alias; pub(crate) mod stmt_while; pub(crate) mod stmt_with; @@ -39,7 +38,6 @@ impl FormatRule> for FormatStmt { fn fmt(&self, item: &Stmt, f: &mut PyFormatter) -> FormatResult<()> { match item { Stmt::FunctionDef(x) => x.format().fmt(f), - Stmt::AsyncFunctionDef(x) => x.format().fmt(f), Stmt::ClassDef(x) => x.format().fmt(f), Stmt::Return(x) => x.format().fmt(f), Stmt::Delete(x) => x.format().fmt(f), @@ -47,15 +45,12 @@ impl FormatRule> for FormatStmt { Stmt::AugAssign(x) => x.format().fmt(f), Stmt::AnnAssign(x) => x.format().fmt(f), Stmt::For(x) => x.format().fmt(f), - Stmt::AsyncFor(x) => x.format().fmt(f), Stmt::While(x) => x.format().fmt(f), Stmt::If(x) => x.format().fmt(f), Stmt::With(x) => x.format().fmt(f), - Stmt::AsyncWith(x) => x.format().fmt(f), Stmt::Match(x) => x.format().fmt(f), Stmt::Raise(x) => x.format().fmt(f), Stmt::Try(x) => x.format().fmt(f), - Stmt::TryStar(x) => x.format().fmt(f), Stmt::Assert(x) => x.format().fmt(f), Stmt::Import(x) => x.format().fmt(f), Stmt::ImportFrom(x) => x.format().fmt(f), @@ -66,7 +61,7 @@ impl FormatRule> for FormatStmt { Stmt::Break(x) => x.format().fmt(f), Stmt::Continue(x) => x.format().fmt(f), Stmt::TypeAlias(x) => x.format().fmt(f), - Stmt::LineMagic(_) => todo!(), + Stmt::IpyEscapeCommand(x) => x.format().fmt(f), } } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs index e4bb2649d8115..ebfb1e0f78588 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs @@ -1,3 +1,4 @@ +use crate::comments::{SourceComment, SuppressionKind}; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; @@ -42,4 +43,12 @@ impl FormatNodeRule for FormatStmtAnnAssign { Ok(()) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_assert.rs b/crates/ruff_python_formatter/src/statement/stmt_assert.rs index c6dae63a178e6..eb5a859a25501 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_assert.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_assert.rs @@ -1,3 +1,5 @@ +use crate::comments::{SourceComment, SuppressionKind}; +use crate::context::PyFormatContext; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::{FormatNodeRule, PyFormatter}; @@ -38,4 +40,12 @@ impl FormatNodeRule for FormatStmtAssert { Ok(()) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_assign.rs index 86e721bac410e..d22e7adb0f713 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_assign.rs @@ -1,6 +1,6 @@ -use ruff_python_ast::{Expr, StmtAssign}; - +use crate::comments::{SourceComment, SuppressionKind}; use ruff_formatter::{format_args, write, FormatError}; +use ruff_python_ast::{Expr, StmtAssign}; use crate::context::{NodeLevel, WithNodeLevel}; use crate::expression::parentheses::{Parentheses, Parenthesize}; @@ -43,18 +43,35 @@ impl FormatNodeRule for FormatStmtAssign { )] ) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } +#[derive(Debug)] struct FormatTargets<'a> { targets: &'a [Expr], } impl Format> for FormatTargets<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { if let Some((first, rest)) = self.targets.split_first() { - let can_omit_parentheses = has_own_parentheses(first); + let comments = f.context().comments(); - let group_id = if can_omit_parentheses { + let parenthesize = if comments.has_leading(first) { + ParenthesizeTarget::Always + } else if has_own_parentheses(first, f.context()).is_some() { + ParenthesizeTarget::Never + } else { + ParenthesizeTarget::IfBreaks + }; + + let group_id = if parenthesize == ParenthesizeTarget::Never { Some(f.group_id("assignment_parentheses")) } else { None @@ -62,17 +79,23 @@ impl Format> for FormatTargets<'_> { let format_first = format_with(|f: &mut PyFormatter| { let mut f = WithNodeLevel::new(NodeLevel::Expression(group_id), f); - if can_omit_parentheses { - write!(f, [first.format().with_options(Parentheses::Never)]) - } else { - write!( - f, - [ - if_group_breaks(&text("(")), - soft_block_indent(&first.format().with_options(Parentheses::Never)), - if_group_breaks(&text(")")) - ] - ) + match parenthesize { + ParenthesizeTarget::Always => { + write!(f, [first.format().with_options(Parentheses::Always)]) + } + ParenthesizeTarget::Never => { + write!(f, [first.format().with_options(Parentheses::Never)]) + } + ParenthesizeTarget::IfBreaks => { + write!( + f, + [ + if_group_breaks(&text("(")), + soft_block_indent(&first.format().with_options(Parentheses::Never)), + if_group_breaks(&text(")")) + ] + ) + } } }); @@ -92,3 +115,10 @@ impl Format> for FormatTargets<'_> { } } } + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum ParenthesizeTarget { + Always, + Never, + IfBreaks, +} diff --git a/crates/ruff_python_formatter/src/statement/stmt_async_for.rs b/crates/ruff_python_formatter/src/statement/stmt_async_for.rs deleted file mode 100644 index f47b3452e2090..0000000000000 --- a/crates/ruff_python_formatter/src/statement/stmt_async_for.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::prelude::*; -use crate::statement::stmt_for::AnyStatementFor; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::FormatResult; -use ruff_python_ast::StmtAsyncFor; - -#[derive(Default)] -pub struct FormatStmtAsyncFor; - -impl FormatNodeRule for FormatStmtAsyncFor { - fn fmt_fields(&self, item: &StmtAsyncFor, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementFor::from(item).fmt(f) - } - - fn fmt_dangling_comments( - &self, - _node: &StmtAsyncFor, - _f: &mut PyFormatter, - ) -> FormatResult<()> { - // Handled in `fmt_fields` - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/statement/stmt_async_function_def.rs b/crates/ruff_python_formatter/src/statement/stmt_async_function_def.rs deleted file mode 100644 index 1ba23722e5a18..0000000000000 --- a/crates/ruff_python_formatter/src/statement/stmt_async_function_def.rs +++ /dev/null @@ -1,24 +0,0 @@ -use ruff_python_ast::StmtAsyncFunctionDef; - -use ruff_python_ast::function::AnyFunctionDefinition; - -use crate::prelude::*; -use crate::FormatNodeRule; - -#[derive(Default)] -pub struct FormatStmtAsyncFunctionDef; - -impl FormatNodeRule for FormatStmtAsyncFunctionDef { - fn fmt_fields(&self, item: &StmtAsyncFunctionDef, f: &mut PyFormatter) -> FormatResult<()> { - AnyFunctionDefinition::from(item).format().fmt(f) - } - - fn fmt_dangling_comments( - &self, - _node: &StmtAsyncFunctionDef, - _f: &mut PyFormatter, - ) -> FormatResult<()> { - // Handled by `AnyFunctionDef` - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/statement/stmt_async_with.rs b/crates/ruff_python_formatter/src/statement/stmt_async_with.rs deleted file mode 100644 index fdd89fdb2f931..0000000000000 --- a/crates/ruff_python_formatter/src/statement/stmt_async_with.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::prelude::*; -use crate::statement::stmt_with::AnyStatementWith; -use crate::FormatNodeRule; -use ruff_python_ast::StmtAsyncWith; - -#[derive(Default)] -pub struct FormatStmtAsyncWith; - -impl FormatNodeRule for FormatStmtAsyncWith { - fn fmt_fields(&self, item: &StmtAsyncWith, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementWith::from(item).fmt(f) - } - - fn fmt_dangling_comments( - &self, - _node: &StmtAsyncWith, - _f: &mut PyFormatter, - ) -> FormatResult<()> { - // Handled in `fmt_fields` - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs index 6123935e49ad6..652247db46606 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs @@ -1,9 +1,11 @@ +use ruff_formatter::write; +use ruff_python_ast::StmtAugAssign; + +use crate::comments::{SourceComment, SuppressionKind}; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; -use crate::{AsFormat, FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{space, text}; -use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::StmtAugAssign; +use crate::prelude::*; +use crate::{AsFormat, FormatNodeRule}; #[derive(Default)] pub struct FormatStmtAugAssign; @@ -28,4 +30,12 @@ impl FormatNodeRule for FormatStmtAugAssign { ] ) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_break.rs b/crates/ruff_python_formatter/src/statement/stmt_break.rs index 3024faae9fd19..b35a884043514 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_break.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_break.rs @@ -1,8 +1,9 @@ -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::text; -use ruff_formatter::{Format, FormatResult}; use ruff_python_ast::StmtBreak; +use crate::comments::{SourceComment, SuppressionKind}; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtBreak; @@ -10,4 +11,12 @@ impl FormatNodeRule for FormatStmtBreak { fn fmt_fields(&self, _item: &StmtBreak, f: &mut PyFormatter) -> FormatResult<()> { text("break").fmt(f) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_class_def.rs b/crates/ruff_python_formatter/src/statement/stmt_class_def.rs index 202afd2f01241..a8f87c46ea95f 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_class_def.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_class_def.rs @@ -1,12 +1,13 @@ -use ruff_python_ast::{Ranged, StmtClassDef}; -use ruff_text_size::TextRange; - use ruff_formatter::write; -use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_python_ast::{Decorator, Ranged, StmtClassDef}; +use ruff_python_trivia::lines_after_ignoring_trivia; -use crate::comments::trailing_comments; -use crate::expression::parentheses::{parenthesized, Parentheses}; +use crate::comments::{leading_comments, trailing_comments, SourceComment}; use crate::prelude::*; +use crate::statement::suite::SuiteKind; + +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; +use crate::FormatNodeRule; #[derive(Default)] pub struct FormatStmtClassDef; @@ -16,50 +17,104 @@ impl FormatNodeRule for FormatStmtClassDef { let StmtClassDef { range: _, name, - bases, - keywords, + arguments, body, - type_params: _, + type_params, decorator_list, } = item; - f.join_with(hard_line_break()) - .entries(decorator_list.iter().formatted()) - .finish()?; - - if !decorator_list.is_empty() { - hard_line_break().fmt(f)?; - } - - write!(f, [text("class"), space(), name.format()])?; + let comments = f.context().comments().clone(); - if !(bases.is_empty() && keywords.is_empty()) { - parenthesized( - "(", - &FormatInheritanceClause { - class_definition: item, - }, - ")", - ) - .fmt(f)?; - } + let dangling_comments = comments.dangling(item); + let trailing_definition_comments_start = + dangling_comments.partition_point(|comment| comment.line_position().is_own_line()); - let comments = f.context().comments().clone(); - let trailing_head_comments = comments.dangling_comments(item); + let (leading_definition_comments, trailing_definition_comments) = + dangling_comments.split_at(trailing_definition_comments_start); write!( f, [ - text(":"), - trailing_comments(trailing_head_comments), - block_indent(&body.format()) + FormatDecorators { + decorators: decorator_list, + leading_definition_comments, + }, + clause_header( + ClauseHeader::Class(item), + trailing_definition_comments, + &format_with(|f| { + write!(f, [text("class"), space(), name.format()])?; + + if let Some(type_params) = type_params.as_deref() { + write!(f, [type_params.format()])?; + } + + if let Some(arguments) = arguments.as_deref() { + // Drop empty the arguments node entirely (i.e., remove the parentheses) if it is empty, + // e.g., given: + // ```python + // class A(): + // ... + // ``` + // + // Format as: + // ```python + // class A: + // ... + // ``` + // + // However, preserve any dangling end-of-line comments, e.g., given: + // ```python + // class A( # comment + // ): + // ... + // + // Format as: + // ```python + // class A: # comment + // ... + // ``` + // + // However, the arguments contain any dangling own-line comments, we retain the + // parentheses, e.g., given: + // ```python + // class A( # comment + // # comment + // ): + // ... + // ``` + // + // Format as: + // ```python + // class A( # comment + // # comment + // ): + // ... + // ``` + if arguments.is_empty() + && comments + .dangling(arguments) + .iter() + .all(|comment| comment.line_position().is_end_of_line()) + { + let dangling = comments.dangling(arguments); + write!(f, [trailing_comments(dangling)])?; + } else { + write!(f, [arguments.format()])?; + } + } + + Ok(()) + }), + ), + clause_body(body, trailing_definition_comments).with_kind(SuiteKind::Class), ] ) } fn fmt_dangling_comments( &self, - _node: &StmtClassDef, + _dangling_comments: &[SourceComment], _f: &mut PyFormatter, ) -> FormatResult<()> { // handled in fmt_fields @@ -67,50 +122,42 @@ impl FormatNodeRule for FormatStmtClassDef { } } -struct FormatInheritanceClause<'a> { - class_definition: &'a StmtClassDef, +pub(super) struct FormatDecorators<'a> { + pub(super) decorators: &'a [Decorator], + pub(super) leading_definition_comments: &'a [SourceComment], } -impl Format> for FormatInheritanceClause<'_> { +impl Format> for FormatDecorators<'_> { fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - let StmtClassDef { - bases, - keywords, - name, - body, - .. - } = self.class_definition; - - let source = f.context().source(); - - let mut joiner = f.join_comma_separated(body.first().unwrap().start()); - - if let Some((first, rest)) = bases.split_first() { - // Manually handle parentheses for the first expression because the logic in `FormatExpr` - // doesn't know that it should disregard the parentheses of the inheritance clause. - // ```python - // class Test(A) # A is not parenthesized, the parentheses belong to the inheritance clause - // class Test((A)) # A is parenthesized - // ``` - // parentheses from the inheritance clause belong to the expression. - let tokenizer = SimpleTokenizer::new(source, TextRange::new(name.end(), first.start())) - .skip_trivia(); - - let left_paren_count = tokenizer - .take_while(|token| token.kind() == SimpleTokenKind::LParen) - .count(); - - // Ignore the first parentheses count - let parentheses = if left_paren_count > 1 { - Parentheses::Always - } else { - Parentheses::Never - }; + if let Some(last_decorator) = self.decorators.last() { + f.join_with(hard_line_break()) + .entries(self.decorators.iter().formatted()) + .finish()?; - joiner.entry(first, &first.format().with_options(parentheses)); - joiner.nodes(rest.iter()); + if self.leading_definition_comments.is_empty() { + write!(f, [hard_line_break()])?; + } else { + // Write any leading definition comments (between last decorator and the header) + // while maintaining the right amount of empty lines between the comment + // and the last decorator. + let leading_line = + if lines_after_ignoring_trivia(last_decorator.end(), f.context().source()) <= 1 + { + hard_line_break() + } else { + empty_line() + }; + + write!( + f, + [ + leading_line, + leading_comments(self.leading_definition_comments) + ] + )?; + } } - joiner.nodes(keywords.iter()).finish() + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_continue.rs b/crates/ruff_python_formatter/src/statement/stmt_continue.rs index 8b2ab90e0e663..88c43877d8e57 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_continue.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_continue.rs @@ -1,8 +1,9 @@ -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::text; -use ruff_formatter::{Format, FormatResult}; +use crate::comments::{SourceComment, SuppressionKind}; use ruff_python_ast::StmtContinue; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtContinue; @@ -10,4 +11,12 @@ impl FormatNodeRule for FormatStmtContinue { fn fmt_fields(&self, _item: &StmtContinue, f: &mut PyFormatter) -> FormatResult<()> { text("continue").fmt(f) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_delete.rs b/crates/ruff_python_formatter/src/statement/stmt_delete.rs index 02dd1f97b1999..7cf79dfe314e8 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_delete.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_delete.rs @@ -1,11 +1,12 @@ +use ruff_formatter::write; +use ruff_python_ast::{Ranged, StmtDelete}; + use crate::builders::{parenthesize_if_expands, PyFormatterExtensions}; -use crate::comments::dangling_node_comments; +use crate::comments::{dangling_node_comments, SourceComment, SuppressionKind}; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{block_indent, format_with, space, text}; -use ruff_formatter::{write, Buffer, Format, FormatResult}; -use ruff_python_ast::{Ranged, StmtDelete}; +use crate::prelude::*; +use crate::FormatNodeRule; #[derive(Default)] pub struct FormatStmtDelete; @@ -26,9 +27,9 @@ impl FormatNodeRule for FormatStmtDelete { // del ( // # Dangling comment // ) - &text("("), + text("("), block_indent(&dangling_node_comments(item)), - &text(")"), + text(")"), ] ) } @@ -53,8 +54,20 @@ impl FormatNodeRule for FormatStmtDelete { } } - fn fmt_dangling_comments(&self, _node: &StmtDelete, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled in `fmt_fields` Ok(()) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_expr.rs b/crates/ruff_python_formatter/src/statement/stmt_expr.rs index 0a3365e2b999a..ff30886fb0db4 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_expr.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_expr.rs @@ -1,3 +1,4 @@ +use crate::comments::{SourceComment, SuppressionKind}; use ruff_python_ast as ast; use ruff_python_ast::{Expr, Operator, StmtExpr}; @@ -19,6 +20,14 @@ impl FormatNodeRule for FormatStmtExpr { value.format().fmt(f) } } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } const fn is_arithmetic_like(expression: &Expr) -> bool { diff --git a/crates/ruff_python_formatter/src/statement/stmt_for.rs b/crates/ruff_python_formatter/src/statement/stmt_for.rs index 701ba12ce15bf..67020e5344349 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_for.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_for.rs @@ -1,19 +1,19 @@ -use crate::comments::{leading_alternate_branch_comments, trailing_comments}; +use ruff_formatter::{format_args, write}; +use ruff_python_ast::{Expr, Ranged, Stmt, StmtFor}; + +use crate::comments::SourceComment; use crate::expression::expr_tuple::TupleParentheses; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::{format_args, write, Buffer, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::{Expr, Ranged, Stmt, StmtAsyncFor, StmtFor, Suite}; -use ruff_text_size::TextRange; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader, ElseClause}; +use crate::FormatNodeRule; #[derive(Debug)] struct ExprTupleWithoutParentheses<'a>(&'a Expr); impl Format> for ExprTupleWithoutParentheses<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { match self.0 { Expr::Tuple(expr_tuple) => expr_tuple .format() @@ -27,85 +27,19 @@ impl Format> for ExprTupleWithoutParentheses<'_> { #[derive(Default)] pub struct FormatStmtFor; -pub(super) enum AnyStatementFor<'a> { - For(&'a StmtFor), - AsyncFor(&'a StmtAsyncFor), -} - -impl<'a> AnyStatementFor<'a> { - const fn is_async(&self) -> bool { - matches!(self, AnyStatementFor::AsyncFor(_)) - } - - fn target(&self) -> &Expr { - match self { - AnyStatementFor::For(stmt) => &stmt.target, - AnyStatementFor::AsyncFor(stmt) => &stmt.target, - } - } - - #[allow(clippy::iter_not_returning_iterator)] - fn iter(&self) -> &Expr { - match self { - AnyStatementFor::For(stmt) => &stmt.iter, - AnyStatementFor::AsyncFor(stmt) => &stmt.iter, - } - } - - fn body(&self) -> &Suite { - match self { - AnyStatementFor::For(stmt) => &stmt.body, - AnyStatementFor::AsyncFor(stmt) => &stmt.body, - } - } - - fn orelse(&self) -> &Suite { - match self { - AnyStatementFor::For(stmt) => &stmt.orelse, - AnyStatementFor::AsyncFor(stmt) => &stmt.orelse, - } - } -} - -impl Ranged for AnyStatementFor<'_> { - fn range(&self) -> TextRange { - match self { - AnyStatementFor::For(stmt) => stmt.range(), - AnyStatementFor::AsyncFor(stmt) => stmt.range(), - } - } -} - -impl<'a> From<&'a StmtFor> for AnyStatementFor<'a> { - fn from(value: &'a StmtFor) -> Self { - AnyStatementFor::For(value) - } -} - -impl<'a> From<&'a StmtAsyncFor> for AnyStatementFor<'a> { - fn from(value: &'a StmtAsyncFor) -> Self { - AnyStatementFor::AsyncFor(value) - } -} - -impl<'a> From<&AnyStatementFor<'a>> for AnyNodeRef<'a> { - fn from(value: &AnyStatementFor<'a>) -> Self { - match value { - AnyStatementFor::For(stmt) => AnyNodeRef::StmtFor(stmt), - AnyStatementFor::AsyncFor(stmt) => AnyNodeRef::StmtAsyncFor(stmt), - } - } -} - -impl Format> for AnyStatementFor<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - let target = self.target(); - let iter = self.iter(); - let body = self.body(); - let orelse = self.orelse(); +impl FormatNodeRule for FormatStmtFor { + fn fmt_fields(&self, item: &StmtFor, f: &mut PyFormatter) -> FormatResult<()> { + let StmtFor { + is_async, + target, + iter, + body, + orelse, + range: _, + } = item; let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(self); + let dangling_comments = comments.dangling(item); let body_start = body.first().map_or(iter.end(), Stmt::start); let or_else_comments_start = dangling_comments.partition_point(|comment| comment.slice().end() < body_start); @@ -116,18 +50,21 @@ impl Format> for AnyStatementFor<'_> { write!( f, [ - self.is_async() - .then_some(format_args![text("async"), space()]), - text("for"), - space(), - ExprTupleWithoutParentheses(target), - space(), - text("in"), - space(), - maybe_parenthesize_expression(iter, self, Parenthesize::IfBreaks), - text(":"), - trailing_comments(trailing_condition_comments), - block_indent(&body.format()) + clause_header( + ClauseHeader::For(item), + trailing_condition_comments, + &format_args![ + is_async.then_some(format_args![text("async"), space()]), + text("for"), + space(), + ExprTupleWithoutParentheses(target), + space(), + text("in"), + space(), + maybe_parenthesize_expression(iter, item, Parenthesize::IfBreaks), + ], + ), + clause_body(body, trailing_condition_comments), ] )?; @@ -143,24 +80,25 @@ impl Format> for AnyStatementFor<'_> { write!( f, [ - leading_alternate_branch_comments(leading, body.last()), - text("else:"), - trailing_comments(trailing), - block_indent(&orelse.format()) + clause_header( + ClauseHeader::OrElse(ElseClause::For(item)), + trailing, + &text("else"), + ) + .with_leading_comments(leading, body.last()), + clause_body(orelse, trailing), ] )?; } Ok(()) } -} - -impl FormatNodeRule for FormatStmtFor { - fn fmt_fields(&self, item: &StmtFor, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementFor::from(item).fmt(f) - } - fn fmt_dangling_comments(&self, _node: &StmtFor, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled in `fmt_fields` Ok(()) } diff --git a/crates/ruff_python_formatter/src/statement/stmt_function_def.rs b/crates/ruff_python_formatter/src/statement/stmt_function_def.rs index 27d569b5b3e1d..764f3487c371f 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_function_def.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_function_def.rs @@ -1,13 +1,14 @@ -use ruff_python_ast::{Ranged, StmtFunctionDef}; +use ruff_formatter::write; +use ruff_python_ast::{Parameters, Ranged, StmtFunctionDef}; +use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; -use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule}; -use ruff_python_ast::function::AnyFunctionDefinition; -use ruff_python_trivia::{lines_after, skip_trailing_trivia}; - -use crate::comments::{leading_comments, trailing_comments}; - -use crate::expression::parentheses::{optional_parentheses, Parentheses}; +use crate::comments::SourceComment; +use crate::expression::maybe_parenthesize_expression; +use crate::expression::parentheses::{Parentheses, Parenthesize}; use crate::prelude::*; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; +use crate::statement::stmt_class_def::FormatDecorators; +use crate::statement::suite::SuiteKind; use crate::FormatNodeRule; #[derive(Default)] @@ -15,129 +16,165 @@ pub struct FormatStmtFunctionDef; impl FormatNodeRule for FormatStmtFunctionDef { fn fmt_fields(&self, item: &StmtFunctionDef, f: &mut PyFormatter) -> FormatResult<()> { - AnyFunctionDefinition::from(item).format().fmt(f) - } - - fn fmt_dangling_comments( - &self, - _node: &StmtFunctionDef, - _f: &mut PyFormatter, - ) -> FormatResult<()> { - // Handled by `AnyFunctionDef` - Ok(()) - } -} - -#[derive(Default)] -pub struct FormatAnyFunctionDef; + let StmtFunctionDef { + range: _, + is_async, + decorator_list, + name, + type_params, + parameters, + returns, + body, + } = item; -impl FormatRule, PyFormatContext<'_>> for FormatAnyFunctionDef { - fn fmt( - &self, - item: &AnyFunctionDefinition<'_>, - f: &mut Formatter>, - ) -> FormatResult<()> { let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(item); + let dangling_comments = comments.dangling(item); let trailing_definition_comments_start = dangling_comments.partition_point(|comment| comment.line_position().is_own_line()); - let (leading_function_definition_comments, trailing_definition_comments) = + let (leading_definition_comments, trailing_definition_comments) = dangling_comments.split_at(trailing_definition_comments_start); - if let Some(last_decorator) = item.decorators().last() { - f.join_with(hard_line_break()) - .entries(item.decorators().iter().formatted()) - .finish()?; - - if leading_function_definition_comments.is_empty() { - write!(f, [hard_line_break()])?; - } else { - // Write any leading function comments (between last decorator and function header) - // while maintaining the right amount of empty lines between the comment - // and the last decorator. - let decorator_end = - skip_trailing_trivia(last_decorator.end(), f.context().source()); - - let leading_line = if lines_after(decorator_end, f.context().source()) <= 1 { - hard_line_break() - } else { - empty_line() - }; - - write!( - f, - [ - leading_line, - leading_comments(leading_function_definition_comments) - ] - )?; - } - } - - if item.is_async() { - write!(f, [text("async"), space()])?; - } - - let name = item.name(); - write!( f, [ - text("def"), - space(), - name.format(), - item.arguments().format(), - ] - )?; - - if let Some(return_annotation) = item.returns() { - write!( - f, - [ - space(), - text("->"), - space(), - optional_parentheses( - &return_annotation.format().with_options(Parentheses::Never) - ) - ] - )?; - } - - write!( - f, - [ - text(":"), - trailing_comments(trailing_definition_comments), - block_indent(&item.body().format()) + FormatDecorators { + decorators: decorator_list, + leading_definition_comments, + }, + clause_header( + ClauseHeader::Function(item), + trailing_definition_comments, + &format_with(|f| { + if *is_async { + write!(f, [text("async"), space()])?; + } + + write!(f, [text("def"), space(), name.format()])?; + + if let Some(type_params) = type_params.as_ref() { + write!(f, [type_params.format()])?; + } + + let format_inner = format_with(|f: &mut PyFormatter| { + write!(f, [parameters.format()])?; + + if let Some(return_annotation) = returns.as_ref() { + write!(f, [space(), text("->"), space()])?; + + if return_annotation.is_tuple_expr() { + let parentheses = + if comments.has_leading(return_annotation.as_ref()) { + Parentheses::Always + } else { + Parentheses::Never + }; + write!( + f, + [return_annotation.format().with_options(parentheses)] + )?; + } else if comments.has_trailing(return_annotation.as_ref()) { + // Intentionally parenthesize any return annotations with trailing comments. + // This avoids an instability in cases like: + // ```python + // def double( + // a: int + // ) -> ( + // int # Hello + // ): + // pass + // ``` + // If we allow this to break, it will be formatted as follows: + // ```python + // def double( + // a: int + // ) -> int: # Hello + // pass + // ``` + // On subsequent formats, the `# Hello` will be interpreted as a dangling + // comment on a function, yielding: + // ```python + // def double(a: int) -> int: # Hello + // pass + // ``` + // Ideally, we'd reach that final formatting in a single pass, but doing so + // requires that the parent be aware of how the child is formatted, which + // is challenging. As a compromise, we break those expressions to avoid an + // instability. + write!( + f, + [return_annotation + .format() + .with_options(Parentheses::Always)] + )?; + } else { + write!( + f, + [maybe_parenthesize_expression( + return_annotation, + item, + if empty_parameters(parameters, f.context().source()) { + // If the parameters are empty, add parentheses if the return annotation + // breaks at all. + Parenthesize::IfBreaksOrIfRequired + } else { + // Otherwise, use our normal rules for parentheses, which allows us to break + // like: + // ```python + // def f( + // x, + // ) -> Tuple[ + // int, + // int, + // ]: + // ... + // ``` + Parenthesize::IfBreaks + }, + )] + )?; + } + } + Ok(()) + }); + + group(&format_inner).fmt(f) + }), + ), + clause_body(body, trailing_definition_comments).with_kind(SuiteKind::Function), ] ) } -} -impl<'def, 'ast> AsFormat> for AnyFunctionDefinition<'def> { - type Format<'a> = FormatRefWithRule< - 'a, - AnyFunctionDefinition<'def>, - FormatAnyFunctionDef, - PyFormatContext<'ast>, - > where Self: 'a; - - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new(self, FormatAnyFunctionDef) + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) } } -impl<'def, 'ast> IntoFormat> for AnyFunctionDefinition<'def> { - type Format = FormatOwnedWithRule< - AnyFunctionDefinition<'def>, - FormatAnyFunctionDef, - PyFormatContext<'ast>, - >; +/// Returns `true` if [`Parameters`] is empty (no parameters, no comments, etc.). +fn empty_parameters(parameters: &Parameters, source: &str) -> bool { + let mut tokenizer = SimpleTokenizer::new(source, parameters.range()) + .filter(|token| !matches!(token.kind, SimpleTokenKind::Whitespace)); - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new(self, FormatAnyFunctionDef) + let Some(lpar) = tokenizer.next() else { + return false; + }; + if !matches!(lpar.kind, SimpleTokenKind::LParen) { + return false; } + + let Some(rpar) = tokenizer.next() else { + return false; + }; + if !matches!(rpar.kind, SimpleTokenKind::RParen) { + return false; + } + + true } diff --git a/crates/ruff_python_formatter/src/statement/stmt_global.rs b/crates/ruff_python_formatter/src/statement/stmt_global.rs index abdaf7c710492..620848c2c9fea 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_global.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_global.rs @@ -1,4 +1,6 @@ +use crate::comments::{SourceComment, SuppressionKind}; use ruff_formatter::{format_args, write}; +use ruff_python_ast::node::AstNode; use ruff_python_ast::StmtGlobal; use crate::prelude::*; @@ -9,10 +11,49 @@ pub struct FormatStmtGlobal; impl FormatNodeRule for FormatStmtGlobal { fn fmt_fields(&self, item: &StmtGlobal, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [text("global"), space()])?; + // Join the `global` names, breaking across continuation lines if necessary, unless the + // `global` statement has a trailing comment, in which case, breaking the names would + // move the comment "off" of the `global` statement. + if f.context().comments().has_trailing(item.as_any_node_ref()) { + let joined = format_with(|f| { + f.join_with(format_args![text(","), space()]) + .entries(item.names.iter().formatted()) + .finish() + }); - f.join_with(format_args![text(","), space()]) - .entries(item.names.iter().formatted()) - .finish() + write!(f, [text("global"), space(), &joined]) + } else { + let joined = format_with(|f| { + f.join_with(&format_args![ + text(","), + space(), + if_group_breaks(&text("\\")), + soft_line_break(), + ]) + .entries(item.names.iter().formatted()) + .finish() + }); + + write!( + f, + [ + text("global"), + space(), + group(&format_args!( + if_group_breaks(&text("\\")), + soft_line_break(), + soft_block_indent(&joined) + )) + ] + ) + } + } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_if.rs b/crates/ruff_python_formatter/src/statement/stmt_if.rs index 7eb8652fc0348..5f19c2cd6c64d 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_if.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_if.rs @@ -1,11 +1,13 @@ -use crate::comments::{leading_alternate_branch_comments, trailing_comments}; +use ruff_formatter::{format_args, write}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{ElifElseClause, StmtIf}; + +use crate::comments::SourceComment; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; use crate::FormatNodeRule; -use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::{ElifElseClause, StmtIf}; #[derive(Default)] pub struct FormatStmtIf; @@ -20,17 +22,21 @@ impl FormatNodeRule for FormatStmtIf { } = item; let comments = f.context().comments().clone(); - let trailing_colon_comment = comments.dangling_comments(item); + let trailing_colon_comment = comments.dangling(item); write!( f, [ - text("if"), - space(), - maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), - text(":"), - trailing_comments(trailing_colon_comment), - block_indent(&body.format()) + clause_header( + ClauseHeader::If(item), + trailing_colon_comment, + &format_args![ + text("if"), + space(), + maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), + ], + ), + clause_body(body, trailing_colon_comment), ] )?; @@ -43,7 +49,11 @@ impl FormatNodeRule for FormatStmtIf { Ok(()) } - fn fmt_dangling_comments(&self, _node: &StmtIf, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled by `fmt_fields` Ok(()) } @@ -63,30 +73,32 @@ pub(crate) fn format_elif_else_clause( } = item; let comments = f.context().comments().clone(); - let trailing_colon_comment = comments.dangling_comments(item); - let leading_comments = comments.leading_comments(item); - - leading_alternate_branch_comments(leading_comments, last_node).fmt(f)?; - - if let Some(test) = test { - write!( - f, - [ - text("elif"), - space(), - maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), - ] - )?; - } else { - text("else").fmt(f)?; - } + let trailing_colon_comment = comments.dangling(item); + let leading_comments = comments.leading(item); write!( f, [ - text(":"), - trailing_comments(trailing_colon_comment), - block_indent(&body.format()) + clause_header( + ClauseHeader::ElifElse(item), + trailing_colon_comment, + &format_with(|f| { + if let Some(test) = test { + write!( + f, + [ + text("elif"), + space(), + maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), + ] + ) + } else { + text("else").fmt(f) + } + }), + ) + .with_leading_comments(leading_comments, last_node), + clause_body(body, trailing_colon_comment), ] ) } diff --git a/crates/ruff_python_formatter/src/statement/stmt_import.rs b/crates/ruff_python_formatter/src/statement/stmt_import.rs index ea781db62533a..a8cdba2d08195 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_import.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_import.rs @@ -1,8 +1,10 @@ -use crate::{FormatNodeRule, FormattedIterExt, PyFormatter}; -use ruff_formatter::prelude::{format_args, format_with, space, text}; -use ruff_formatter::{write, Buffer, FormatResult}; +use crate::prelude::*; +use ruff_formatter::{format_args, write}; use ruff_python_ast::StmtImport; +use crate::comments::{SourceComment, SuppressionKind}; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtImport; @@ -16,4 +18,12 @@ impl FormatNodeRule for FormatStmtImport { }); write!(f, [text("import"), space(), names]) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs index e6164aa66dff0..fb894f7e2badf 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs @@ -1,9 +1,13 @@ -use crate::builders::{parenthesize_if_expands, PyFormatterExtensions}; -use crate::{AsFormat, FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{dynamic_text, format_with, space, text}; -use ruff_formatter::{write, Buffer, Format, FormatResult}; +use ruff_formatter::write; +use ruff_python_ast::node::AstNode; use ruff_python_ast::{Ranged, StmtImportFrom}; +use crate::builders::{parenthesize_if_expands, PyFormatterExtensions, TrailingComma}; +use crate::comments::{SourceComment, SuppressionKind}; +use crate::expression::parentheses::parenthesized; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtImportFrom; @@ -12,8 +16,8 @@ impl FormatNodeRule for FormatStmtImportFrom { let StmtImportFrom { module, names, - range: _, level, + range: _, } = item; let level_str = level @@ -32,17 +36,54 @@ impl FormatNodeRule for FormatStmtImportFrom { space(), ] )?; + if let [name] = names.as_slice() { // star can't be surrounded by parentheses if name.name.as_str() == "*" { return text("*").fmt(f); } } + let names = format_with(|f| { f.join_comma_separated(item.end()) + .with_trailing_comma(TrailingComma::OneOrMore) .entries(names.iter().map(|name| (name, name.format()))) .finish() }); - parenthesize_if_expands(&names).fmt(f) + + // A dangling comment on an import is a parenthesized comment, like: + // ```python + // from example import ( # comment + // A, + // B, + // ) + // ``` + let comments = f.context().comments().clone(); + let parenthesized_comments = comments.dangling(item.as_any_node_ref()); + + if parenthesized_comments.is_empty() { + parenthesize_if_expands(&names).fmt(f) + } else { + parenthesized("(", &names, ")") + .with_dangling_comments(parenthesized_comments) + .fmt(f) + } + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) + } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_ipy_escape_command.rs b/crates/ruff_python_formatter/src/statement/stmt_ipy_escape_command.rs new file mode 100644 index 0000000000000..6af1da6ad2616 --- /dev/null +++ b/crates/ruff_python_formatter/src/statement/stmt_ipy_escape_command.rs @@ -0,0 +1,20 @@ +use crate::comments::{SourceComment, SuppressionKind}; +use crate::prelude::*; +use ruff_python_ast::{Ranged, StmtIpyEscapeCommand}; + +#[derive(Default)] +pub struct FormatStmtIpyEscapeCommand; + +impl FormatNodeRule for FormatStmtIpyEscapeCommand { + fn fmt_fields(&self, item: &StmtIpyEscapeCommand, f: &mut PyFormatter) -> FormatResult<()> { + source_text_slice(item.range(), ContainsNewlines::No).fmt(f) + } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } +} diff --git a/crates/ruff_python_formatter/src/statement/stmt_match.rs b/crates/ruff_python_formatter/src/statement/stmt_match.rs index 073acc17224d0..9b1a3b1ad3a36 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_match.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_match.rs @@ -1,12 +1,76 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_formatter::{format_args, write}; use ruff_python_ast::StmtMatch; +use crate::comments::{leading_alternate_branch_comments, SourceComment}; +use crate::context::{NodeLevel, WithNodeLevel}; +use crate::expression::maybe_parenthesize_expression; +use crate::expression::parentheses::Parenthesize; +use crate::prelude::*; +use crate::statement::clause::{clause_header, ClauseHeader}; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtMatch; impl FormatNodeRule for FormatStmtMatch { fn fmt_fields(&self, item: &StmtMatch, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let StmtMatch { + range: _, + subject, + cases, + } = item; + + let comments = f.context().comments().clone(); + let dangling_item_comments = comments.dangling(item); + + // There can be at most one dangling comment after the colon in a match statement. + debug_assert!(dangling_item_comments.len() <= 1); + + clause_header( + ClauseHeader::Match(item), + dangling_item_comments, + &format_args![ + text("match"), + space(), + maybe_parenthesize_expression(subject, item, Parenthesize::IfBreaks), + ], + ) + .fmt(f)?; + + let mut cases_iter = cases.iter(); + let Some(first) = cases_iter.next() else { + return Ok(()); + }; + + // The new level is for the `case` nodes. + let mut f = WithNodeLevel::new(NodeLevel::CompoundStatement, f); + + write!(f, [block_indent(&first.format())])?; + let mut last_case = first; + + for case in cases_iter { + write!( + f, + [block_indent(&format_args!( + leading_alternate_branch_comments( + comments.leading(case), + last_case.body.last(), + ), + case.format() + ))] + )?; + last_case = case; + } + + Ok(()) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled as part of `fmt_fields` + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs b/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs index f3dd3b1966165..c185b2ec69876 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs @@ -1,4 +1,6 @@ +use crate::comments::{SourceComment, SuppressionKind}; use ruff_formatter::{format_args, write}; +use ruff_python_ast::node::AstNode; use ruff_python_ast::StmtNonlocal; use crate::prelude::*; @@ -9,10 +11,49 @@ pub struct FormatStmtNonlocal; impl FormatNodeRule for FormatStmtNonlocal { fn fmt_fields(&self, item: &StmtNonlocal, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [text("nonlocal"), space()])?; + // Join the `nonlocal` names, breaking across continuation lines if necessary, unless the + // `nonlocal` statement has a trailing comment, in which case, breaking the names would + // move the comment "off" of the `nonlocal` statement. + if f.context().comments().has_trailing(item.as_any_node_ref()) { + let joined = format_with(|f| { + f.join_with(format_args![text(","), space()]) + .entries(item.names.iter().formatted()) + .finish() + }); - f.join_with(format_args![text(","), space()]) - .entries(item.names.iter().formatted()) - .finish() + write!(f, [text("nonlocal"), space(), &joined]) + } else { + let joined = format_with(|f| { + f.join_with(&format_args![ + text(","), + space(), + if_group_breaks(&text("\\")), + soft_line_break(), + ]) + .entries(item.names.iter().formatted()) + .finish() + }); + + write!( + f, + [ + text("nonlocal"), + space(), + group(&format_args!( + if_group_breaks(&text("\\")), + soft_line_break(), + soft_block_indent(&joined) + )) + ] + ) + } + } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_pass.rs b/crates/ruff_python_formatter/src/statement/stmt_pass.rs index 18afe6bbb6a65..b0cc9bd12345c 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_pass.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_pass.rs @@ -1,8 +1,9 @@ -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::text; -use ruff_formatter::{Format, FormatResult}; +use crate::comments::{SourceComment, SuppressionKind}; use ruff_python_ast::StmtPass; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtPass; @@ -10,4 +11,12 @@ impl FormatNodeRule for FormatStmtPass { fn fmt_fields(&self, _item: &StmtPass, f: &mut PyFormatter) -> FormatResult<()> { text("pass").fmt(f) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_raise.rs b/crates/ruff_python_formatter/src/statement/stmt_raise.rs index 411b6e1b8f6d6..1f69f4084cab4 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_raise.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_raise.rs @@ -1,10 +1,11 @@ -use crate::expression::parentheses::Parenthesize; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{space, text}; -use ruff_formatter::{write, Buffer, Format, FormatResult}; +use crate::comments::{SourceComment, SuppressionKind}; +use ruff_formatter::write; +use ruff_python_ast::StmtRaise; use crate::expression::maybe_parenthesize_expression; -use ruff_python_ast::StmtRaise; +use crate::expression::parentheses::Parenthesize; +use crate::prelude::*; +use crate::FormatNodeRule; #[derive(Default)] pub struct FormatStmtRaise; @@ -42,4 +43,12 @@ impl FormatNodeRule for FormatStmtRaise { } Ok(()) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_return.rs b/crates/ruff_python_formatter/src/statement/stmt_return.rs index 01b6e2bec9ff9..133f130e80e78 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_return.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_return.rs @@ -1,9 +1,11 @@ +use ruff_formatter::write; +use ruff_python_ast::StmtReturn; + +use crate::comments::{SourceComment, SuppressionKind}; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::prelude::{space, text}; -use ruff_formatter::{write, Buffer, Format, FormatResult}; -use ruff_python_ast::StmtReturn; +use crate::prelude::*; +use crate::FormatNodeRule; #[derive(Default)] pub struct FormatStmtReturn; @@ -24,4 +26,12 @@ impl FormatNodeRule for FormatStmtReturn { text("return").fmt(f) } } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_try.rs b/crates/ruff_python_formatter/src/statement/stmt_try.rs index 57f30dd09f308..cfae87be7d6eb 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_try.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_try.rs @@ -1,86 +1,14 @@ +use ruff_formatter::{write, FormatRuleWithOptions}; +use ruff_python_ast::{ExceptHandler, Ranged, StmtTry}; + use crate::comments; +use crate::comments::leading_alternate_branch_comments; use crate::comments::SourceComment; -use crate::comments::{leading_alternate_branch_comments, trailing_comments}; use crate::other::except_handler_except_handler::ExceptHandlerKind; use crate::prelude::*; -use crate::statement::FormatRefWithRule; -use crate::statement::Stmt; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader, ElseClause}; +use crate::statement::{FormatRefWithRule, Stmt}; use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::FormatRuleWithOptions; -use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; -use ruff_python_ast::{ExceptHandler, Ranged, StmtTry, StmtTryStar, Suite}; -use ruff_text_size::TextRange; - -pub(super) enum AnyStatementTry<'a> { - Try(&'a StmtTry), - TryStar(&'a StmtTryStar), -} -impl<'a> AnyStatementTry<'a> { - const fn except_handler_kind(&self) -> ExceptHandlerKind { - match self { - AnyStatementTry::Try(_) => ExceptHandlerKind::Regular, - AnyStatementTry::TryStar(_) => ExceptHandlerKind::Starred, - } - } - - fn body(&self) -> &Suite { - match self { - AnyStatementTry::Try(try_) => &try_.body, - AnyStatementTry::TryStar(try_) => &try_.body, - } - } - - fn handlers(&self) -> &[ExceptHandler] { - match self { - AnyStatementTry::Try(try_) => try_.handlers.as_slice(), - AnyStatementTry::TryStar(try_) => try_.handlers.as_slice(), - } - } - fn orelse(&self) -> &Suite { - match self { - AnyStatementTry::Try(try_) => &try_.orelse, - AnyStatementTry::TryStar(try_) => &try_.orelse, - } - } - - fn finalbody(&self) -> &Suite { - match self { - AnyStatementTry::Try(try_) => &try_.finalbody, - AnyStatementTry::TryStar(try_) => &try_.finalbody, - } - } -} - -impl Ranged for AnyStatementTry<'_> { - fn range(&self) -> TextRange { - match self { - AnyStatementTry::Try(with) => with.range(), - AnyStatementTry::TryStar(with) => with.range(), - } - } -} - -impl<'a> From<&'a StmtTry> for AnyStatementTry<'a> { - fn from(value: &'a StmtTry) -> Self { - AnyStatementTry::Try(value) - } -} - -impl<'a> From<&'a StmtTryStar> for AnyStatementTry<'a> { - fn from(value: &'a StmtTryStar) -> Self { - AnyStatementTry::TryStar(value) - } -} - -impl<'a> From<&AnyStatementTry<'a>> for AnyNodeRef<'a> { - fn from(value: &AnyStatementTry<'a>) -> Self { - match value { - AnyStatementTry::Try(with) => AnyNodeRef::StmtTry(with), - AnyStatementTry::TryStar(with) => AnyNodeRef::StmtTryStar(with), - } - } -} #[derive(Default)] pub struct FormatStmtTry; @@ -100,15 +28,12 @@ impl FormatRuleWithOptions> for FormatExceptH } impl FormatRule> for FormatExceptHandler { - fn fmt( - &self, - item: &ExceptHandler, - f: &mut Formatter>, - ) -> FormatResult<()> { + fn fmt(&self, item: &ExceptHandler, f: &mut PyFormatter) -> FormatResult<()> { match item { - ExceptHandler::ExceptHandler(x) => { - x.format().with_options(self.except_handler_kind).fmt(f) - } + ExceptHandler::ExceptHandler(except_handler) => except_handler + .format() + .with_options(self.except_handler_kind) + .fmt(f), } } } @@ -125,25 +50,35 @@ impl<'ast> AsFormat> for ExceptHandler { FormatRefWithRule::new(self, FormatExceptHandler::default()) } } -impl Format> for AnyStatementTry<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + +impl FormatNodeRule for FormatStmtTry { + fn fmt_fields(&self, item: &StmtTry, f: &mut PyFormatter) -> FormatResult<()> { + let StmtTry { + body, + handlers, + orelse: _, + finalbody: _, + is_star, + range: _, + } = item; + let comments_info = f.context().comments().clone(); - let mut dangling_comments = comments_info.dangling_comments(self); - let body = self.body(); - let handlers = self.handlers(); - let orelse = self.orelse(); - let finalbody = self.finalbody(); + let mut dangling_comments = comments_info.dangling(item); - (_, dangling_comments) = format_case("try", body, None, dangling_comments, f)?; + (_, dangling_comments) = format_case(item, CaseKind::Try, None, dangling_comments, f)?; let mut previous_node = body.last(); for handler in handlers { - let handler_comments = comments_info.leading_comments(handler); + let handler_comments = comments_info.leading(handler); write!( f, [ leading_alternate_branch_comments(handler_comments, previous_node), - &handler.format().with_options(self.except_handler_kind()), + &handler.format().with_options(if *is_star { + ExceptHandlerKind::Starred + } else { + ExceptHandlerKind::Regular + }), ] )?; previous_node = match handler { @@ -152,50 +87,79 @@ impl Format> for AnyStatementTry<'_> { } (previous_node, dangling_comments) = - format_case("else", orelse, previous_node, dangling_comments, f)?; + format_case(item, CaseKind::Else, previous_node, dangling_comments, f)?; - format_case("finally", finalbody, previous_node, dangling_comments, f)?; + format_case(item, CaseKind::Finally, previous_node, dangling_comments, f)?; write!(f, [comments::dangling_comments(dangling_comments)]) } -} - -impl FormatNodeRule for FormatStmtTry { - fn fmt_fields(&self, item: &StmtTry, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementTry::from(item).fmt(f) - } - fn fmt_dangling_comments(&self, _node: &StmtTry, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // dangling comments are formatted as part of AnyStatementTry::fmt Ok(()) } } fn format_case<'a>( - name: &'static str, - body: &Suite, - previous_node: Option<&Stmt>, + try_statement: &'a StmtTry, + kind: CaseKind, + previous_node: Option<&'a Stmt>, dangling_comments: &'a [SourceComment], f: &mut PyFormatter, ) -> FormatResult<(Option<&'a Stmt>, &'a [SourceComment])> { + let body = match kind { + CaseKind::Try => &try_statement.body, + CaseKind::Else => &try_statement.orelse, + CaseKind::Finally => &try_statement.finalbody, + }; + Ok(if let Some(last) = body.last() { let case_comments_start = dangling_comments.partition_point(|comment| comment.slice().end() <= last.end()); let (case_comments, rest) = dangling_comments.split_at(case_comments_start); let partition_point = case_comments.partition_point(|comment| comment.line_position().is_own_line()); + + let (leading_case_comments, trailing_case_comments) = + case_comments.split_at(partition_point); + + let header = match kind { + CaseKind::Try => ClauseHeader::Try(try_statement), + CaseKind::Else => ClauseHeader::OrElse(ElseClause::Try(try_statement)), + CaseKind::Finally => ClauseHeader::TryFinally(try_statement), + }; + write!( f, [ - leading_alternate_branch_comments(&case_comments[..partition_point], previous_node), - text(name), - text(":"), - trailing_comments(&case_comments[partition_point..]), - block_indent(&body.format()) + clause_header(header, trailing_case_comments, &text(kind.keyword())) + .with_leading_comments(leading_case_comments, previous_node), + clause_body(body, trailing_case_comments), ] )?; - (None, rest) + (Some(last), rest) } else { - (None, dangling_comments) + (previous_node, dangling_comments) }) } + +#[derive(Copy, Clone)] +enum CaseKind { + Try, + Else, + Finally, +} + +impl CaseKind { + fn keyword(self) -> &'static str { + match self { + CaseKind::Try => "try", + CaseKind::Else => "else", + CaseKind::Finally => "finally", + } + } +} diff --git a/crates/ruff_python_formatter/src/statement/stmt_try_star.rs b/crates/ruff_python_formatter/src/statement/stmt_try_star.rs deleted file mode 100644 index 3c20fc42ee997..0000000000000 --- a/crates/ruff_python_formatter/src/statement/stmt_try_star.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::statement::stmt_try::AnyStatementTry; -use crate::{FormatNodeRule, PyFormatter}; -use ruff_formatter::Format; -use ruff_formatter::FormatResult; -use ruff_python_ast::StmtTryStar; - -#[derive(Default)] -pub struct FormatStmtTryStar; - -impl FormatNodeRule for FormatStmtTryStar { - fn fmt_fields(&self, item: &StmtTryStar, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementTry::from(item).fmt(f) - } - - fn fmt_dangling_comments(&self, _node: &StmtTryStar, _f: &mut PyFormatter) -> FormatResult<()> { - // dangling comments are formatted as part of AnyStatementTry::fmt - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs b/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs index d731ed2de4ff7..4c1be677189e5 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs @@ -1,17 +1,46 @@ -use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use crate::comments::{SourceComment, SuppressionKind}; +use ruff_formatter::write; use ruff_python_ast::StmtTypeAlias; +use crate::expression::maybe_parenthesize_expression; +use crate::expression::parentheses::Parenthesize; +use crate::prelude::*; +use crate::FormatNodeRule; + #[derive(Default)] pub struct FormatStmtTypeAlias; impl FormatNodeRule for FormatStmtTypeAlias { - fn fmt_fields(&self, _item: &StmtTypeAlias, f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_fields(&self, item: &StmtTypeAlias, f: &mut PyFormatter) -> FormatResult<()> { + let StmtTypeAlias { + name, + type_params, + value, + range: _, + } = item; + + write!(f, [text("type"), space(), name.as_ref().format()])?; + + if let Some(type_params) = type_params { + write!(f, [type_params.format()])?; + } + write!( f, - [not_yet_implemented_custom_text( - "type NOT_YET_IMPLEMENTED_type_alias = int" - )] + [ + space(), + text("="), + space(), + maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) + ] ) } + + fn is_suppressed( + &self, + trailing_comments: &[SourceComment], + context: &PyFormatContext, + ) -> bool { + SuppressionKind::has_skip_comment(trailing_comments, context.source()) + } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_while.rs b/crates/ruff_python_formatter/src/statement/stmt_while.rs index 3ee9e1a7a3552..e409978b6c48a 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_while.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_while.rs @@ -1,11 +1,13 @@ -use crate::comments::{leading_alternate_branch_comments, trailing_comments}; +use ruff_formatter::{format_args, write}; +use ruff_python_ast::node::AstNode; +use ruff_python_ast::{Ranged, Stmt, StmtWhile}; + +use crate::comments::SourceComment; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader, ElseClause}; use crate::FormatNodeRule; -use ruff_formatter::write; -use ruff_python_ast::node::AstNode; -use ruff_python_ast::{Ranged, Stmt, StmtWhile}; #[derive(Default)] pub struct FormatStmtWhile; @@ -20,7 +22,7 @@ impl FormatNodeRule for FormatStmtWhile { } = item; let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(item.as_any_node_ref()); + let dangling_comments = comments.dangling(item.as_any_node_ref()); let body_start = body.first().map_or(test.end(), Stmt::start); let or_else_comments_start = @@ -32,12 +34,16 @@ impl FormatNodeRule for FormatStmtWhile { write!( f, [ - text("while"), - space(), - maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), - text(":"), - trailing_comments(trailing_condition_comments), - block_indent(&body.format()) + clause_header( + ClauseHeader::While(item), + trailing_condition_comments, + &format_args![ + text("while"), + space(), + maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), + ] + ), + clause_body(body, trailing_condition_comments), ] )?; @@ -51,10 +57,13 @@ impl FormatNodeRule for FormatStmtWhile { write!( f, [ - leading_alternate_branch_comments(leading, body.last()), - text("else:"), - trailing_comments(trailing), - block_indent(&orelse.format()) + clause_header( + ClauseHeader::OrElse(ElseClause::While(item)), + trailing, + &text("else") + ) + .with_leading_comments(leading, body.last()), + clause_body(orelse, trailing), ] )?; } @@ -62,7 +71,11 @@ impl FormatNodeRule for FormatStmtWhile { Ok(()) } - fn fmt_dangling_comments(&self, _node: &StmtWhile, _f: &mut PyFormatter) -> FormatResult<()> { + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { // Handled in `fmt_fields` Ok(()) } diff --git a/crates/ruff_python_formatter/src/statement/stmt_with.rs b/crates/ruff_python_formatter/src/statement/stmt_with.rs index 4cb4d2f5040b0..55383ef564c80 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_with.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_with.rs @@ -1,129 +1,164 @@ -use ruff_python_ast::{Ranged, StmtAsyncWith, StmtWith, Suite, WithItem}; -use ruff_text_size::TextRange; - use ruff_formatter::{format_args, write, FormatError}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::node::AstNode; +use ruff_python_ast::{Ranged, StmtWith}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; +use ruff_text_size::TextRange; -use crate::comments::trailing_comments; +use crate::builders::parenthesize_if_expands; +use crate::comments::SourceComment; use crate::expression::parentheses::{ - in_parentheses_only_soft_line_break_or_space, optional_parentheses, + in_parentheses_only_soft_line_break_or_space, optional_parentheses, parenthesized, }; +use crate::other::commas; use crate::prelude::*; -use crate::FormatNodeRule; +use crate::statement::clause::{clause_body, clause_header, ClauseHeader}; +use crate::{FormatNodeRule, PyFormatOptions}; -pub(super) enum AnyStatementWith<'a> { - With(&'a StmtWith), - AsyncWith(&'a StmtAsyncWith), -} +#[derive(Default)] +pub struct FormatStmtWith; -impl<'a> AnyStatementWith<'a> { - const fn is_async(&self) -> bool { - matches!(self, AnyStatementWith::AsyncWith(_)) - } +impl FormatNodeRule for FormatStmtWith { + fn fmt_fields(&self, item: &StmtWith, f: &mut PyFormatter) -> FormatResult<()> { + // The `with` statement can have one dangling comment on the open parenthesis, like: + // ```python + // with ( # comment + // CtxManager() as example + // ): + // ... + // ``` + // + // Any other dangling comments are trailing comments on the colon, like: + // ```python + // with CtxManager() as example: # comment + // ... + // ``` + let comments = f.context().comments().clone(); + let dangling_comments = comments.dangling(item.as_any_node_ref()); + let partition_point = dangling_comments.partition_point(|comment| { + item.items + .first() + .is_some_and(|with_item| with_item.start() > comment.start()) + }); + let (parenthesized_comments, colon_comments) = dangling_comments.split_at(partition_point); - fn items(&self) -> &[WithItem] { - match self { - AnyStatementWith::With(with) => with.items.as_slice(), - AnyStatementWith::AsyncWith(with) => with.items.as_slice(), - } + write!( + f, + [ + clause_header( + ClauseHeader::With(item), + colon_comments, + &format_with(|f| { + write!( + f, + [ + item.is_async + .then_some(format_args![text("async"), space()]), + text("with"), + space() + ] + )?; + + if !parenthesized_comments.is_empty() { + let joined = format_with(|f: &mut PyFormatter| { + f.join_comma_separated(item.body.first().unwrap().start()) + .nodes(&item.items) + .finish() + }); + + parenthesized("(", &joined, ")") + .with_dangling_comments(parenthesized_comments) + .fmt(f)?; + } else if should_parenthesize(item, f.options(), f.context())? { + parenthesize_if_expands(&format_with(|f| { + let mut joiner = + f.join_comma_separated(item.body.first().unwrap().start()); + + for item in &item.items { + joiner.entry_with_line_separator( + item, + &item.format(), + in_parentheses_only_soft_line_break_or_space(), + ); + } + joiner.finish() + })) + .fmt(f)?; + } else if let [item] = item.items.as_slice() { + // This is similar to `maybe_parenthesize_expression`, but we're not dealing with an + // expression here, it's a `WithItem`. + if comments.has_leading(item) || comments.has_trailing_own_line(item) { + optional_parentheses(&item.format()).fmt(f)?; + } else { + item.format().fmt(f)?; + } + } else { + f.join_with(format_args![text(","), space()]) + .entries(item.items.iter().formatted()) + .finish()?; + } + + Ok(()) + }) + ), + clause_body(&item.body, colon_comments) + ] + ) } - fn body(&self) -> &Suite { - match self { - AnyStatementWith::With(with) => &with.body, - AnyStatementWith::AsyncWith(with) => &with.body, - } + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) } } -impl Ranged for AnyStatementWith<'_> { - fn range(&self) -> TextRange { - match self { - AnyStatementWith::With(with) => with.range(), - AnyStatementWith::AsyncWith(with) => with.range(), - } +/// Returns `true` if the `with` items should be parenthesized, if at least one item expands. +/// +/// Black parenthesizes `with` items if there's more than one item and they're already +/// parenthesized, _or_ there's a single item with a trailing comma. +fn should_parenthesize( + with: &StmtWith, + options: &PyFormatOptions, + context: &PyFormatContext, +) -> FormatResult { + if has_magic_trailing_comma(with, options, context) { + return Ok(true); } -} -impl<'a> From<&'a StmtWith> for AnyStatementWith<'a> { - fn from(value: &'a StmtWith) -> Self { - AnyStatementWith::With(value) + if are_with_items_parenthesized(with, context)? { + return Ok(true); } -} -impl<'a> From<&'a StmtAsyncWith> for AnyStatementWith<'a> { - fn from(value: &'a StmtAsyncWith) -> Self { - AnyStatementWith::AsyncWith(value) - } + Ok(false) } -impl<'a> From<&AnyStatementWith<'a>> for AnyNodeRef<'a> { - fn from(value: &AnyStatementWith<'a>) -> Self { - match value { - AnyStatementWith::With(with) => AnyNodeRef::StmtWith(with), - AnyStatementWith::AsyncWith(with) => AnyNodeRef::StmtAsyncWith(with), - } - } +fn has_magic_trailing_comma( + with: &StmtWith, + options: &PyFormatOptions, + context: &PyFormatContext, +) -> bool { + let Some(last_item) = with.items.last() else { + return false; + }; + + commas::has_magic_trailing_comma( + TextRange::new(last_item.end(), with.end()), + options, + context, + ) } -impl Format> for AnyStatementWith<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - let comments = f.context().comments().clone(); - let dangling_comments = comments.dangling_comments(self); +fn are_with_items_parenthesized(with: &StmtWith, context: &PyFormatContext) -> FormatResult { + let [first_item, _, ..] = with.items.as_slice() else { + return Ok(false); + }; - write!( - f, - [ - self.is_async() - .then_some(format_args![text("async"), space()]), - text("with"), - space() - ] - )?; - - if are_with_items_parenthesized(self, f.context())? { - optional_parentheses(&format_with(|f| { - let mut joiner = f.join_comma_separated(self.body().first().unwrap().start()); - - for item in self.items() { - joiner.entry_with_line_separator( - item, - &item.format(), - in_parentheses_only_soft_line_break_or_space(), - ); - } - joiner.finish() - })) - .fmt(f)?; - } else { - f.join_with(format_args![text(","), space()]) - .entries(self.items().iter().formatted()) - .finish()?; - } - - write!( - f, - [ - text(":"), - trailing_comments(dangling_comments), - block_indent(&self.body().format()) - ] - ) - } -} - -fn are_with_items_parenthesized( - with: &AnyStatementWith, - context: &PyFormatContext, -) -> FormatResult { - let first_with_item = with - .items() - .first() - .ok_or(FormatError::syntax_error("Expected at least one with item"))?; - let before_first_with_item = TextRange::new(with.start(), first_with_item.start()); + let before_first_item = TextRange::new(with.start(), first_item.start()); - let mut tokenizer = SimpleTokenizer::new(context.source(), before_first_with_item) + let mut tokenizer = SimpleTokenizer::new(context.source(), before_first_item) .skip_trivia() .skip_while(|t| t.kind() == SimpleTokenKind::Async); @@ -145,17 +180,3 @@ fn are_with_items_parenthesized( None => Ok(false), } } - -#[derive(Default)] -pub struct FormatStmtWith; - -impl FormatNodeRule for FormatStmtWith { - fn fmt_fields(&self, item: &StmtWith, f: &mut PyFormatter) -> FormatResult<()> { - AnyStatementWith::from(item).fmt(f) - } - - fn fmt_dangling_comments(&self, _node: &StmtWith, _f: &mut PyFormatter) -> FormatResult<()> { - // Handled in `fmt_fields` - Ok(()) - } -} diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index 735cf6cc63abc..24dca3ffc2a17 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -1,74 +1,211 @@ +use crate::comments::{leading_comments, trailing_comments, Comments}; use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; use ruff_python_ast::helpers::is_compound_statement; -use ruff_python_ast::{Ranged, Stmt, Suite}; -use ruff_python_trivia::{lines_after, lines_before, skip_trailing_trivia}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{self as ast, Constant, Expr, ExprConstant, Ranged, Stmt, Suite}; +use ruff_python_trivia::{lines_after_ignoring_trivia, lines_before}; +use ruff_text_size::TextRange; use crate::context::{NodeLevel, WithNodeLevel}; +use crate::expression::expr_constant::ExprConstantLayout; +use crate::expression::string::StringLayout; use crate::prelude::*; +use crate::statement::stmt_expr::FormatStmtExpr; +use crate::verbatim::{ + suppressed_node, write_suppressed_statements_starting_with_leading_comment, + write_suppressed_statements_starting_with_trailing_comment, +}; /// Level at which the [`Suite`] appears in the source code. -#[derive(Copy, Clone, Debug)] -pub enum SuiteLevel { +#[derive(Copy, Clone, Debug, Default)] +pub enum SuiteKind { /// Statements at the module level / top level TopLevel, - /// Statements in a nested body - Nested, -} + /// Statements in a function body. + Function, -impl SuiteLevel { - const fn is_nested(self) -> bool { - matches!(self, SuiteLevel::Nested) - } + /// Statements in a class body. + Class, + + /// Statements in any other body (e.g., `if` or `while`). + #[default] + Other, } #[derive(Debug)] pub struct FormatSuite { - level: SuiteLevel, + kind: SuiteKind, } impl Default for FormatSuite { fn default() -> Self { FormatSuite { - level: SuiteLevel::Nested, + kind: SuiteKind::Other, } } } impl FormatRule> for FormatSuite { fn fmt(&self, statements: &Suite, f: &mut PyFormatter) -> FormatResult<()> { - let node_level = match self.level { - SuiteLevel::TopLevel => NodeLevel::TopLevel, - SuiteLevel::Nested => NodeLevel::CompoundStatement, + let node_level = match self.kind { + SuiteKind::TopLevel => NodeLevel::TopLevel, + SuiteKind::Function | SuiteKind::Class | SuiteKind::Other => { + NodeLevel::CompoundStatement + } }; let comments = f.context().comments().clone(); let source = f.context().source(); + let source_type = f.options().source_type(); + + let f = &mut WithNodeLevel::new(node_level, f); let mut iter = statements.iter(); let Some(first) = iter.next() else { return Ok(()); }; - let mut f = WithNodeLevel::new(node_level, f); - // First entry has never any separator, doesn't matter which one we take. - write!(f, [first.format()])?; + // Format the first statement in the body, which often has special formatting rules. + let first = match self.kind { + SuiteKind::Other => { + if is_class_or_function_definition(first) && !comments.has_leading(first) { + // Add an empty line for any nested functions or classes defined within + // non-function or class compound statements, e.g., this is stable formatting: + // ```python + // if True: + // + // def test(): + // ... + // ``` + empty_line().fmt(f)?; + } + + SuiteChildStatement::Other(first) + } - let mut last = first; + SuiteKind::Function => { + if let Some(docstring) = DocstringStmt::try_from_statement(first) { + SuiteChildStatement::Docstring(docstring) + } else { + SuiteChildStatement::Other(first) + } + } - for statement in iter { - if is_class_or_function_definition(last) || is_class_or_function_definition(statement) { - match self.level { - SuiteLevel::TopLevel => { - write!(f, [empty_line(), empty_line(), statement.format()])?; + SuiteKind::Class => { + if let Some(docstring) = DocstringStmt::try_from_statement(first) { + if !comments.has_leading(first) && lines_before(first.start(), source) > 1 { + // Allow up to one empty line before a class docstring, e.g., this is + // stable formatting: + // ```python + // class Test: + // + // """Docstring""" + // ``` + empty_line().fmt(f)?; } - SuiteLevel::Nested => { - write!(f, [empty_line(), statement.format()])?; + + SuiteChildStatement::Docstring(docstring) + } else { + SuiteChildStatement::Other(first) + } + } + SuiteKind::TopLevel => SuiteChildStatement::Other(first), + }; + + let first_comments = comments.leading_dangling_trailing(first); + + let (mut preceding, mut after_class_docstring) = if first_comments + .leading + .iter() + .any(|comment| comment.is_suppression_off_comment(source)) + { + ( + write_suppressed_statements_starting_with_leading_comment(first, &mut iter, f)?, + false, + ) + } else if first_comments + .trailing + .iter() + .any(|comment| comment.is_suppression_off_comment(source)) + { + ( + write_suppressed_statements_starting_with_trailing_comment(first, &mut iter, f)?, + false, + ) + } else { + first.fmt(f)?; + ( + first.statement(), + matches!(first, SuiteChildStatement::Docstring(_)) + && matches!(self.kind, SuiteKind::Class), + ) + }; + + while let Some(following) = iter.next() { + if is_class_or_function_definition(preceding) + || is_class_or_function_definition(following) + { + match self.kind { + SuiteKind::TopLevel if source_type.is_stub() => { + // Preserve the empty line if the definitions are separated by a comment + if comments.has_trailing(preceding) || comments.has_leading(following) { + empty_line().fmt(f)?; + } else { + // Two subsequent classes that both have an ellipsis only body + // ```python + // class A: ... + // class B: ... + // ``` + let class_sequences_with_ellipsis_only = + preceding.as_class_def_stmt().is_some_and(|class| { + contains_only_an_ellipsis(&class.body, f.context().comments()) + }) && following.as_class_def_stmt().is_some_and(|class| { + contains_only_an_ellipsis(&class.body, f.context().comments()) + }); + + // Two subsequent functions where the preceding has an ellipsis only body + // ```python + // def test(): ... + // def b(): a + // ``` + let function_with_ellipsis = + preceding.as_function_def_stmt().is_some_and(|function| { + contains_only_an_ellipsis( + &function.body, + f.context().comments(), + ) + }) && following.is_function_def_stmt(); + + // Don't add an empty line between two classes that have an `...` body only or after + // a function with an `...` body. Otherwise add an empty line. + if !class_sequences_with_ellipsis_only && !function_with_ellipsis { + empty_line().fmt(f)?; + } + } + } + SuiteKind::TopLevel => { + write!(f, [empty_line(), empty_line()])?; + } + SuiteKind::Function | SuiteKind::Class | SuiteKind::Other => { + empty_line().fmt(f)?; + } + } + } else if is_import_definition(preceding) && !is_import_definition(following) { + // Enforce _at least_ one empty line after an import statement (but allow up to + // two at the top-level). + match self.kind { + SuiteKind::TopLevel => { + match lines_after_ignoring_trivia(preceding.end(), source) { + 0 | 1 | 2 => empty_line().fmt(f)?, + _ => write!(f, [empty_line(), empty_line()])?, + } + } + SuiteKind::Function | SuiteKind::Class | SuiteKind::Other => { + empty_line().fmt(f)?; } } - } else if is_import_definition(last) && !is_import_definition(statement) { - write!(f, [empty_line(), statement.format()])?; - } else if is_compound_statement(last) { + } else if is_compound_statement(preceding) { // Handles the case where a body has trailing comments. The issue is that RustPython does not include // the comments in the range of the suite. This means, the body ends right after the last statement in the body. // ```python @@ -85,26 +222,40 @@ impl FormatRule> for FormatSuite { // which is 0 instead of 1, the number of lines between the trailing comment and // the leading comment. This is why the suite handling counts the lines before the // start of the next statement or before the first leading comments for compound statements. - let start = - if let Some(first_leading) = comments.leading_comments(statement).first() { - first_leading.slice().start() - } else { - statement.start() - }; + let start = if let Some(first_leading) = comments.leading(following).first() { + first_leading.slice().start() + } else { + following.start() + }; match lines_before(start, source) { - 0 | 1 => write!(f, [hard_line_break()])?, - 2 => write!(f, [empty_line()])?, - 3.. => { - if self.level.is_nested() { - write!(f, [empty_line()])?; - } else { - write!(f, [empty_line(), empty_line()])?; + 0 | 1 => hard_line_break().fmt(f)?, + 2 => empty_line().fmt(f)?, + 3.. => match self.kind { + SuiteKind::TopLevel => write!(f, [empty_line(), empty_line()])?, + SuiteKind::Function | SuiteKind::Class | SuiteKind::Other => { + empty_line().fmt(f)?; } - } + }, } - - write!(f, [statement.format()])?; + } else if after_class_docstring { + // Enforce an empty line after a class docstring, e.g., these are both stable + // formatting: + // ```python + // class Test: + // """Docstring""" + // + // ... + // + // + // class Test: + // + // """Docstring""" + // + // ... + // ``` + empty_line().fmt(f)?; + after_class_docstring = false; } else { // Insert the appropriate number of empty lines based on the node level, e.g.: // * [`NodeLevel::Module`]: Up to two empty lines @@ -124,41 +275,79 @@ impl FormatRule> for FormatSuite { // it then counts the lines between the statement and the trailing comment, which is // always 0. This is why it skips any trailing trivia (trivia that's on the same line) // and counts the lines after. - let after_trailing_trivia = skip_trailing_trivia(offset, source); - lines_after(after_trailing_trivia, source) + lines_after_ignoring_trivia(offset, source) }; match node_level { - NodeLevel::TopLevel => match count_lines(last.end()) { - 0 | 1 => write!(f, [hard_line_break()])?, - 2 => write!(f, [empty_line()])?, + NodeLevel::TopLevel => match count_lines(preceding.end()) { + 0 | 1 => hard_line_break().fmt(f)?, + 2 => empty_line().fmt(f)?, _ => write!(f, [empty_line(), empty_line()])?, }, - NodeLevel::CompoundStatement => match count_lines(last.end()) { - 0 | 1 => write!(f, [hard_line_break()])?, - _ => write!(f, [empty_line()])?, + NodeLevel::CompoundStatement => match count_lines(preceding.end()) { + 0 | 1 => hard_line_break().fmt(f)?, + _ => empty_line().fmt(f)?, }, NodeLevel::Expression(_) | NodeLevel::ParenthesizedExpression => { - write!(f, [hard_line_break()])?; + hard_line_break().fmt(f)?; } } - - write!(f, [statement.format()])?; } - last = statement; + let following_comments = comments.leading_dangling_trailing(following); + + if following_comments + .leading + .iter() + .any(|comment| comment.is_suppression_off_comment(source)) + { + preceding = write_suppressed_statements_starting_with_leading_comment( + SuiteChildStatement::Other(following), + &mut iter, + f, + )?; + } else if following_comments + .trailing + .iter() + .any(|comment| comment.is_suppression_off_comment(source)) + { + preceding = write_suppressed_statements_starting_with_trailing_comment( + SuiteChildStatement::Other(following), + &mut iter, + f, + )?; + } else { + following.format().fmt(f)?; + preceding = following; + } } Ok(()) } } +/// Returns `true` if a function or class body contains only an ellipsis with no comments. +pub(crate) fn contains_only_an_ellipsis(body: &[Stmt], comments: &Comments) -> bool { + match body { + [Stmt::Expr(ast::StmtExpr { value, .. })] => { + let [node] = body else { + return false; + }; + matches!( + value.as_ref(), + Expr::Constant(ast::ExprConstant { + value: Constant::Ellipsis, + .. + }) + ) && !comments.has_leading(node) + } + _ => false, + } +} + /// Returns `true` if a [`Stmt`] is a class or function definition. const fn is_class_or_function_definition(stmt: &Stmt) -> bool { - matches!( - stmt, - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) - ) + matches!(stmt, Stmt::FunctionDef(_) | Stmt::ClassDef(_)) } /// Returns `true` if a [`Stmt`] is an import. @@ -167,10 +356,10 @@ const fn is_import_definition(stmt: &Stmt) -> bool { } impl FormatRuleWithOptions> for FormatSuite { - type Options = SuiteLevel; + type Options = SuiteKind; fn with_options(mut self, options: Self::Options) -> Self { - self.level = options; + self.kind = options; self } } @@ -191,18 +380,110 @@ impl<'ast> IntoFormat> for Suite { } } +/// A statement representing a docstring. +#[derive(Copy, Clone)] +pub(crate) struct DocstringStmt<'a>(&'a Stmt); + +impl<'a> DocstringStmt<'a> { + /// Checks if the statement is a simple string that can be formatted as a docstring + fn try_from_statement(stmt: &'a Stmt) -> Option> { + let Stmt::Expr(ast::StmtExpr { value, .. }) = stmt else { + return None; + }; + + if let Expr::Constant(ExprConstant { value, .. }) = value.as_ref() { + if !value.is_implicit_concatenated() { + return Some(DocstringStmt(stmt)); + } + } + + None + } +} + +impl Format> for DocstringStmt<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let comments = f.context().comments().clone(); + let node_comments = comments.leading_dangling_trailing(self.0); + + if FormatStmtExpr.is_suppressed(node_comments.trailing, f.context()) { + suppressed_node(self.0).fmt(f) + } else { + // SAFETY: Safe because `DocStringStmt` guarantees that it only ever wraps a `ExprStmt` containing a `ConstantExpr`. + let constant = self + .0 + .as_expr_stmt() + .unwrap() + .value + .as_constant_expr() + .unwrap(); + + // We format the expression, but the statement carries the comments + write!( + f, + [ + leading_comments(node_comments.leading), + constant + .format() + .with_options(ExprConstantLayout::String(StringLayout::DocString)), + trailing_comments(node_comments.trailing), + ] + ) + } + } +} + +/// A Child of a suite. +#[derive(Copy, Clone)] +pub(crate) enum SuiteChildStatement<'a> { + /// A docstring documenting a class or function definition. + Docstring(DocstringStmt<'a>), + + /// Any other statement. + Other(&'a Stmt), +} + +impl<'a> SuiteChildStatement<'a> { + pub(crate) const fn statement(self) -> &'a Stmt { + match self { + SuiteChildStatement::Docstring(docstring) => docstring.0, + SuiteChildStatement::Other(statement) => statement, + } + } +} + +impl Ranged for SuiteChildStatement<'_> { + fn range(&self) -> TextRange { + self.statement().range() + } +} + +impl<'a> From> for AnyNodeRef<'a> { + fn from(value: SuiteChildStatement<'a>) -> Self { + value.statement().into() + } +} + +impl Format> for SuiteChildStatement<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + match self { + SuiteChildStatement::Docstring(docstring) => docstring.fmt(f), + SuiteChildStatement::Other(statement) => statement.format().fmt(f), + } + } +} + #[cfg(test)] mod tests { use ruff_formatter::format; - use ruff_python_ast::Suite; - use ruff_python_parser::Parse; + use ruff_python_parser::parse_suite; use crate::comments::Comments; use crate::prelude::*; - use crate::statement::suite::SuiteLevel; + use crate::statement::suite::SuiteKind; use crate::PyFormatOptions; - fn format_suite(level: SuiteLevel) -> String { + fn format_suite(level: SuiteKind) -> String { let source = r#" a = 10 @@ -224,7 +505,7 @@ def trailing_func(): pass "#; - let statements = Suite::parse(source, "test.py").unwrap(); + let statements = parse_suite(source, "test.py").unwrap(); let context = PyFormatContext::new(PyFormatOptions::default(), source, Comments::default()); @@ -239,7 +520,7 @@ def trailing_func(): #[test] fn top_level() { - let formatted = format_suite(SuiteLevel::TopLevel); + let formatted = format_suite(SuiteKind::TopLevel); assert_eq!( formatted, @@ -274,7 +555,7 @@ def trailing_func(): #[test] fn nested_level() { - let formatted = format_suite(SuiteLevel::Nested); + let formatted = format_suite(SuiteKind::Other); assert_eq!( formatted, diff --git a/crates/ruff_python_formatter/src/type_param/mod.rs b/crates/ruff_python_formatter/src/type_param/mod.rs new file mode 100644 index 0000000000000..07c5f0349f88e --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/mod.rs @@ -0,0 +1,37 @@ +use crate::prelude::*; +use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule}; +use ruff_python_ast::TypeParam; + +pub(crate) mod type_param_param_spec; +pub(crate) mod type_param_type_var; +pub(crate) mod type_param_type_var_tuple; +pub(crate) mod type_params; + +#[derive(Default)] +pub struct FormatTypeParam; + +impl FormatRule> for FormatTypeParam { + fn fmt(&self, item: &TypeParam, f: &mut PyFormatter) -> FormatResult<()> { + match item { + TypeParam::TypeVar(x) => x.format().fmt(f), + TypeParam::TypeVarTuple(x) => x.format().fmt(f), + TypeParam::ParamSpec(x) => x.format().fmt(f), + } + } +} + +impl<'ast> AsFormat> for TypeParam { + type Format<'a> = FormatRefWithRule<'a, TypeParam, FormatTypeParam, PyFormatContext<'ast>>; + + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new(self, FormatTypeParam) + } +} + +impl<'ast> IntoFormat> for TypeParam { + type Format = FormatOwnedWithRule>; + + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new(self, FormatTypeParam) + } +} diff --git a/crates/ruff_python_formatter/src/type_param/type_param_clause.rs b/crates/ruff_python_formatter/src/type_param/type_param_clause.rs new file mode 100644 index 0000000000000..18549e26c215f --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/type_param_clause.rs @@ -0,0 +1,29 @@ +use crate::builders::PyFormatterExtensions; +use crate::context::PyFormatContext; +use crate::expression::parentheses::parenthesized; +use crate::prelude::*; +use ruff_formatter::{Format, FormatResult}; +use ruff_python_ast::TypeParam; +use ruff_text_size::TextSize; + +pub(crate) struct FormatTypeParamsClause<'a> { + pub(crate) sequence_end: TextSize, + pub(crate) type_params: &'a Vec, +} + +/// Formats a sequence of [`TypeParam`] nodes. +impl Format> for FormatTypeParamsClause<'_> { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + if self.type_params.is_empty() { + return Ok(()); + } + + let items = format_with(|f| { + f.join_comma_separated(self.sequence_end) + .nodes(self.type_params.iter()) + .finish() + }); + + parenthesized("[", &items, "]").fmt(f) + } +} diff --git a/crates/ruff_python_formatter/src/type_param/type_param_param_spec.rs b/crates/ruff_python_formatter/src/type_param/type_param_param_spec.rs new file mode 100644 index 0000000000000..ad99dfc4c5088 --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/type_param_param_spec.rs @@ -0,0 +1,14 @@ +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::text; +use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::TypeParamParamSpec; + +#[derive(Default)] +pub struct FormatTypeParamParamSpec; + +impl FormatNodeRule for FormatTypeParamParamSpec { + fn fmt_fields(&self, item: &TypeParamParamSpec, f: &mut PyFormatter) -> FormatResult<()> { + let TypeParamParamSpec { range: _, name } = item; + write!(f, [text("**"), name.format()]) + } +} diff --git a/crates/ruff_python_formatter/src/type_param/type_param_type_var.rs b/crates/ruff_python_formatter/src/type_param/type_param_type_var.rs new file mode 100644 index 0000000000000..c6f9812cbb339 --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/type_param_type_var.rs @@ -0,0 +1,22 @@ +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::{space, text}; +use ruff_formatter::{write, Buffer, Format, FormatResult}; +use ruff_python_ast::TypeParamTypeVar; + +#[derive(Default)] +pub struct FormatTypeParamTypeVar; + +impl FormatNodeRule for FormatTypeParamTypeVar { + fn fmt_fields(&self, item: &TypeParamTypeVar, f: &mut PyFormatter) -> FormatResult<()> { + let TypeParamTypeVar { + range: _, + name, + bound, + } = item; + name.format().fmt(f)?; + if let Some(bound) = bound { + write!(f, [text(":"), space(), bound.format()])?; + } + Ok(()) + } +} diff --git a/crates/ruff_python_formatter/src/type_param/type_param_type_var_tuple.rs b/crates/ruff_python_formatter/src/type_param/type_param_type_var_tuple.rs new file mode 100644 index 0000000000000..d9e6640822ef6 --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/type_param_type_var_tuple.rs @@ -0,0 +1,14 @@ +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::text; +use ruff_formatter::{write, Buffer, FormatResult}; +use ruff_python_ast::TypeParamTypeVarTuple; + +#[derive(Default)] +pub struct FormatTypeParamTypeVarTuple; + +impl FormatNodeRule for FormatTypeParamTypeVarTuple { + fn fmt_fields(&self, item: &TypeParamTypeVarTuple, f: &mut PyFormatter) -> FormatResult<()> { + let TypeParamTypeVarTuple { range: _, name } = item; + write!(f, [text("*"), name.format()]) + } +} diff --git a/crates/ruff_python_formatter/src/type_param/type_params.rs b/crates/ruff_python_formatter/src/type_param/type_params.rs new file mode 100644 index 0000000000000..456d54d5e0f5c --- /dev/null +++ b/crates/ruff_python_formatter/src/type_param/type_params.rs @@ -0,0 +1,45 @@ +use crate::builders::PyFormatterExtensions; +use crate::comments::{trailing_comments, SourceComment}; +use crate::expression::parentheses::parenthesized; +use crate::prelude::*; +use ruff_formatter::write; +use ruff_formatter::FormatResult; +use ruff_python_ast::node::AstNode; + +use ruff_python_ast::{Ranged, TypeParams}; + +#[derive(Default)] +pub struct FormatTypeParams; + +/// Formats a sequence of [`TypeParam`] nodes. +impl FormatNodeRule for FormatTypeParams { + fn fmt_fields(&self, item: &TypeParams, f: &mut PyFormatter) -> FormatResult<()> { + // A dangling comment indicates a comment on the same line as the opening bracket, e.g.: + // ```python + // type foo[ # This type parameter clause has a dangling comment. + // a, + // b, + // c, + // ] = ... + let comments = f.context().comments().clone(); + let dangling_comments = comments.dangling(item.as_any_node_ref()); + write!(f, [trailing_comments(dangling_comments)])?; + + let items = format_with(|f| { + f.join_comma_separated(item.end()) + .nodes(item.type_params.iter()) + .finish() + }); + + parenthesized("[", &items, "]").fmt(f) + } + + fn fmt_dangling_comments( + &self, + _dangling_comments: &[SourceComment], + _f: &mut PyFormatter, + ) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) + } +} diff --git a/crates/ruff_python_formatter/src/verbatim.rs b/crates/ruff_python_formatter/src/verbatim.rs new file mode 100644 index 0000000000000..eb3322d11f898 --- /dev/null +++ b/crates/ruff_python_formatter/src/verbatim.rs @@ -0,0 +1,957 @@ +use std::borrow::Cow; +use std::iter::FusedIterator; + +use unicode_width::UnicodeWidthStr; + +use ruff_formatter::{write, FormatError}; +use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::{Ranged, Stmt}; +use ruff_python_parser::lexer::{lex_starts_at, LexResult}; +use ruff_python_parser::{Mode, Tok}; +use ruff_python_trivia::lines_before; +use ruff_source_file::Locator; +use ruff_text_size::{TextRange, TextSize}; + +use crate::comments::format::{empty_lines, format_comment}; +use crate::comments::{leading_comments, trailing_comments, SourceComment}; +use crate::prelude::*; +use crate::statement::clause::ClauseHeader; +use crate::statement::suite::SuiteChildStatement; + +/// Disables formatting for all statements between the `first_suppressed` that has a leading `fmt: off` comment +/// and the first trailing or leading `fmt: on` comment. The statements are formatted as they appear in the source code. +/// +/// Returns the last formatted statement. +/// +/// ## Panics +/// If `first_suppressed` has no leading suppression comment. +#[cold] +pub(crate) fn write_suppressed_statements_starting_with_leading_comment<'a>( + // The first suppressed statement + first_suppressed: SuiteChildStatement<'a>, + statements: &mut std::slice::Iter<'a, Stmt>, + f: &mut PyFormatter, +) -> FormatResult<&'a Stmt> { + let comments = f.context().comments().clone(); + let source = f.context().source(); + + let mut leading_comment_ranges = + CommentRangeIter::outside_suppression(comments.leading(first_suppressed), source); + + let before_format_off = leading_comment_ranges + .next() + .expect("Suppressed node to have leading comments"); + + let (formatted_comments, format_off_comment) = before_format_off.unwrap_suppression_starts(); + + // Format the leading comments before the fmt off + // ```python + // # leading comment that gets formatted + // # fmt: off + // statement + // ``` + write!( + f, + [ + leading_comments(formatted_comments), + // Format the off comment without adding any trailing new lines + format_comment(format_off_comment) + ] + )?; + + format_off_comment.mark_formatted(); + + // Now inside a suppressed range + write_suppressed_statements( + format_off_comment, + first_suppressed, + leading_comment_ranges.as_slice(), + statements, + f, + ) +} + +/// Disables formatting for all statements between the `last_formatted` and the first trailing or leading `fmt: on` comment. +/// The statements are formatted as they appear in the source code. +/// +/// Returns the last formatted statement. +/// +/// ## Panics +/// If `last_formatted` has no trailing suppression comment. +#[cold] +pub(crate) fn write_suppressed_statements_starting_with_trailing_comment<'a>( + last_formatted: SuiteChildStatement<'a>, + statements: &mut std::slice::Iter<'a, Stmt>, + f: &mut PyFormatter, +) -> FormatResult<&'a Stmt> { + let comments = f.context().comments().clone(); + let source = f.context().source(); + let indentation = Indentation::from_stmt(last_formatted.statement(), source); + + let trailing_node_comments = comments.trailing(last_formatted); + let mut trailing_comment_ranges = + CommentRangeIter::outside_suppression(trailing_node_comments, source); + + // Formatted comments gets formatted as part of the statement. + let (_, mut format_off_comment) = trailing_comment_ranges + .next() + .expect("Suppressed statement to have trailing comments") + .unwrap_suppression_starts(); + + let maybe_suppressed = trailing_comment_ranges.as_slice(); + + // Mark them as formatted so that calling the node's formatting doesn't format the comments. + for comment in maybe_suppressed { + comment.mark_formatted(); + } + format_off_comment.mark_formatted(); + + // Format the leading comments, the node, and the trailing comments up to the `fmt: off` comment. + last_formatted.fmt(f)?; + + format_off_comment.mark_unformatted(); + TrailingFormatOffComment(format_off_comment).fmt(f)?; + + for range in trailing_comment_ranges { + match range { + // A `fmt: off`..`fmt: on` sequence. Disable formatting for the in-between comments. + // ```python + // def test(): + // pass + // # fmt: off + // # haha + // # fmt: on + // # fmt: off (maybe) + // ``` + SuppressionComments::SuppressionEnds { + suppressed_comments: _, + format_on_comment, + formatted_comments, + format_off_comment: new_format_off_comment, + } => { + format_on_comment.mark_unformatted(); + + for comment in formatted_comments { + comment.mark_unformatted(); + } + + write!( + f, + [ + FormatVerbatimStatementRange { + verbatim_range: TextRange::new( + format_off_comment.end(), + format_on_comment.start(), + ), + indentation + }, + trailing_comments(std::slice::from_ref(format_on_comment)), + trailing_comments(formatted_comments), + ] + )?; + + // `fmt: off`..`fmt:on`..`fmt:off` sequence + // ```python + // def test(): + // pass + // # fmt: off + // # haha + // # fmt: on + // # fmt: off + // ``` + if let Some(new_format_off_comment) = new_format_off_comment { + new_format_off_comment.mark_unformatted(); + + TrailingFormatOffComment(new_format_off_comment).fmt(f)?; + + format_off_comment = new_format_off_comment; + } else { + // `fmt: off`..`fmt:on` sequence. The suppression ends here. Start formatting the nodes again. + return Ok(last_formatted.statement()); + } + } + + // All comments in this range are suppressed + SuppressionComments::Suppressed { comments: _ } => {} + // SAFETY: Unreachable because the function returns as soon as it reaches the end of the suppressed range + SuppressionComments::SuppressionStarts { .. } + | SuppressionComments::Formatted { .. } => unreachable!(), + } + } + + // The statement with the suppression comment isn't the last statement in the suite. + // Format the statements up to the first `fmt: on` comment (or end of the suite) as verbatim/suppressed. + // ```python + // a + b + // # fmt: off + // + // def a(): + // pass + // ``` + if let Some(first_suppressed) = statements.next() { + write_suppressed_statements( + format_off_comment, + SuiteChildStatement::Other(first_suppressed), + comments.leading(first_suppressed), + statements, + f, + ) + } + // The suppression comment is the block's last node. Format any trailing comments as suppressed + // ```python + // def test(): + // pass + // # fmt: off + // # a trailing comment + // ``` + else if let Some(last_comment) = trailing_node_comments.last() { + FormatVerbatimStatementRange { + verbatim_range: TextRange::new(format_off_comment.end(), last_comment.end()), + indentation, + } + .fmt(f)?; + Ok(last_formatted.statement()) + } + // The suppression comment is the very last code in the block. There's nothing more to format. + // ```python + // def test(): + // pass + // # fmt: off + // ``` + else { + Ok(last_formatted.statement()) + } +} + +/// Formats the statements from `first_suppressed` until the suppression ends (by a `fmt: on` comment) +/// as they appear in the source code. +fn write_suppressed_statements<'a>( + // The `fmt: off` comment that starts the suppressed range. Can be a leading comment of `first_suppressed` or + // a trailing comment of the previous node. + format_off_comment: &SourceComment, + // The first suppressed statement + first_suppressed: SuiteChildStatement<'a>, + // The leading comments of `first_suppressed` that come after the `format_off_comment` + first_suppressed_leading_comments: &[SourceComment], + // The remaining statements + statements: &mut std::slice::Iter<'a, Stmt>, + f: &mut PyFormatter, +) -> FormatResult<&'a Stmt> { + let comments = f.context().comments().clone(); + let source = f.context().source(); + + let mut statement = first_suppressed; + let mut leading_node_comments = first_suppressed_leading_comments; + let mut format_off_comment = format_off_comment; + let indentation = Indentation::from_stmt(first_suppressed.statement(), source); + + loop { + for range in CommentRangeIter::in_suppression(leading_node_comments, source) { + match range { + // All leading comments are suppressed + // ```python + // # suppressed comment + // statement + // ``` + SuppressionComments::Suppressed { comments } => { + for comment in comments { + comment.mark_formatted(); + } + } + + // Node has a leading `fmt: on` comment and maybe another `fmt: off` comment + // ```python + // # suppressed comment (optional) + // # fmt: on + // # formatted comment (optional) + // # fmt: off (optional) + // statement + // ``` + SuppressionComments::SuppressionEnds { + suppressed_comments, + format_on_comment, + formatted_comments, + format_off_comment: new_format_off_comment, + } => { + for comment in suppressed_comments { + comment.mark_formatted(); + } + + write!( + f, + [ + FormatVerbatimStatementRange { + verbatim_range: TextRange::new( + format_off_comment.end(), + format_on_comment.start(), + ), + indentation + }, + leading_comments(std::slice::from_ref(format_on_comment)), + leading_comments(formatted_comments), + ] + )?; + + if let Some(new_format_off_comment) = new_format_off_comment { + format_off_comment = new_format_off_comment; + format_comment(format_off_comment).fmt(f)?; + format_off_comment.mark_formatted(); + } else { + // Suppression ends here. Test if the node has a trailing suppression comment and, if so, + // recurse and format the trailing comments and the following statements as suppressed. + return if comments + .trailing(statement) + .iter() + .any(|comment| comment.is_suppression_off_comment(source)) + { + // Node has a trailing suppression comment, hell yeah, start all over again. + write_suppressed_statements_starting_with_trailing_comment( + statement, statements, f, + ) + } else { + // Formats the trailing comments + statement.fmt(f)?; + Ok(statement.statement()) + }; + } + } + + // Unreachable because the function exits as soon as it reaches the end of the suppression + // and it already starts in a suppressed range. + SuppressionComments::SuppressionStarts { .. } => unreachable!(), + SuppressionComments::Formatted { .. } => unreachable!(), + } + } + + comments.mark_verbatim_node_comments_formatted(AnyNodeRef::from(statement)); + + for range in CommentRangeIter::in_suppression(comments.trailing(statement), source) { + match range { + // All leading comments are suppressed + // ```python + // statement + // # suppressed + // ``` + SuppressionComments::Suppressed { comments } => { + for comment in comments { + comment.mark_formatted(); + } + } + + // Node has a trailing `fmt: on` comment and maybe another `fmt: off` comment + // ```python + // statement + // # suppressed comment (optional) + // # fmt: on + // # formatted comment (optional) + // # fmt: off (optional) + // ``` + SuppressionComments::SuppressionEnds { + suppressed_comments, + format_on_comment, + formatted_comments, + format_off_comment: new_format_off_comment, + } => { + for comment in suppressed_comments { + comment.mark_formatted(); + } + + write!( + f, + [ + FormatVerbatimStatementRange { + verbatim_range: TextRange::new( + format_off_comment.end(), + format_on_comment.start() + ), + indentation + }, + format_comment(format_on_comment), + hard_line_break(), + trailing_comments(formatted_comments), + ] + )?; + + format_on_comment.mark_formatted(); + + if let Some(new_format_off_comment) = new_format_off_comment { + format_off_comment = new_format_off_comment; + format_comment(format_off_comment).fmt(f)?; + format_off_comment.mark_formatted(); + } else { + return Ok(statement.statement()); + } + } + + // Unreachable because the function exits as soon as it reaches the end of the suppression + // and it already starts in a suppressed range. + SuppressionComments::SuppressionStarts { .. } => unreachable!(), + SuppressionComments::Formatted { .. } => unreachable!(), + } + } + + if let Some(next_statement) = statements.next() { + statement = SuiteChildStatement::Other(next_statement); + leading_node_comments = comments.leading(next_statement); + } else { + let end = comments + .trailing(statement) + .last() + .map_or(statement.end(), Ranged::end); + + FormatVerbatimStatementRange { + verbatim_range: TextRange::new(format_off_comment.end(), end), + indentation, + } + .fmt(f)?; + + return Ok(statement.statement()); + } + } +} + +#[derive(Copy, Clone, Debug)] +enum InSuppression { + No, + Yes, +} + +#[derive(Debug)] +enum SuppressionComments<'a> { + /// The first `fmt: off` comment. + SuppressionStarts { + /// The comments appearing before the `fmt: off` comment + formatted_comments: &'a [SourceComment], + format_off_comment: &'a SourceComment, + }, + + /// A `fmt: on` comment inside a suppressed range. + SuppressionEnds { + /// The comments before the `fmt: on` comment that should *not* be formatted. + suppressed_comments: &'a [SourceComment], + format_on_comment: &'a SourceComment, + + /// The comments after the `fmt: on` comment (if any), that should be formatted. + formatted_comments: &'a [SourceComment], + + /// Any following `fmt: off` comment if any. + /// * `None`: The suppression ends here (for good) + /// * `Some`: A `fmt: off`..`fmt: on` .. `fmt: off` sequence. The suppression continues after + /// the `fmt: off` comment. + format_off_comment: Option<&'a SourceComment>, + }, + + /// Comments that all fall into the suppressed range. + Suppressed { comments: &'a [SourceComment] }, + + /// Comments that all fall into the formatted range. + Formatted { + #[allow(unused)] + comments: &'a [SourceComment], + }, +} + +impl<'a> SuppressionComments<'a> { + fn unwrap_suppression_starts(&self) -> (&'a [SourceComment], &'a SourceComment) { + if let SuppressionComments::SuppressionStarts { + formatted_comments, + format_off_comment, + } = self + { + (formatted_comments, *format_off_comment) + } else { + panic!("Expected SuppressionStarts") + } + } +} + +struct CommentRangeIter<'a> { + comments: &'a [SourceComment], + source: &'a str, + in_suppression: InSuppression, +} + +impl<'a> CommentRangeIter<'a> { + fn in_suppression(comments: &'a [SourceComment], source: &'a str) -> Self { + Self { + comments, + in_suppression: InSuppression::Yes, + source, + } + } + + fn outside_suppression(comments: &'a [SourceComment], source: &'a str) -> Self { + Self { + comments, + in_suppression: InSuppression::No, + source, + } + } + + /// Returns a slice containing the remaining comments. + fn as_slice(&self) -> &'a [SourceComment] { + self.comments + } +} + +impl<'a> Iterator for CommentRangeIter<'a> { + type Item = SuppressionComments<'a>; + + fn next(&mut self) -> Option { + if self.comments.is_empty() { + return None; + } + + Some(match self.in_suppression { + // Inside of a suppressed range + InSuppression::Yes => { + if let Some(format_on_position) = self + .comments + .iter() + .position(|comment| comment.is_suppression_on_comment(self.source)) + { + let (suppressed_comments, formatted) = + self.comments.split_at(format_on_position); + let (format_on_comment, rest) = formatted.split_first().unwrap(); + + let (formatted_comments, format_off_comment) = + if let Some(format_off_position) = rest + .iter() + .position(|comment| comment.is_suppression_off_comment(self.source)) + { + let (formatted_comments, suppressed_comments) = + rest.split_at(format_off_position); + let (format_off_comment, rest) = + suppressed_comments.split_first().unwrap(); + + self.comments = rest; + + (formatted_comments, Some(format_off_comment)) + } else { + self.in_suppression = InSuppression::No; + + self.comments = &[]; + (rest, None) + }; + + SuppressionComments::SuppressionEnds { + suppressed_comments, + format_on_comment, + formatted_comments, + format_off_comment, + } + } else { + SuppressionComments::Suppressed { + comments: std::mem::take(&mut self.comments), + } + } + } + + // Outside of a suppression + InSuppression::No => { + if let Some(format_off_position) = self + .comments + .iter() + .position(|comment| comment.is_suppression_off_comment(self.source)) + { + self.in_suppression = InSuppression::Yes; + + let (formatted_comments, suppressed) = + self.comments.split_at(format_off_position); + let format_off_comment = &suppressed[0]; + + self.comments = &suppressed[1..]; + + SuppressionComments::SuppressionStarts { + formatted_comments, + format_off_comment, + } + } else { + SuppressionComments::Formatted { + comments: std::mem::take(&mut self.comments), + } + } + } + }) + } +} + +impl FusedIterator for CommentRangeIter<'_> {} + +struct TrailingFormatOffComment<'a>(&'a SourceComment); + +impl Format> for TrailingFormatOffComment<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + debug_assert!(self.0.is_unformatted()); + let lines_before_comment = lines_before(self.0.start(), f.context().source()); + + write!( + f, + [empty_lines(lines_before_comment), format_comment(self.0)] + )?; + + self.0.mark_formatted(); + + Ok(()) + } +} + +/// Stores the indentation of a statement by storing the number of indentation characters. +/// Storing the number of indentation characters is sufficient because: +/// * Two indentations are equal if they result in the same column, regardless of the used tab size. +/// This implementation makes use of this fact and assumes a tab size of 1. +/// * The source document is correctly indented because it is valid Python code (or the formatter would have failed parsing the code). +#[derive(Copy, Clone)] +struct Indentation(u32); + +impl Indentation { + fn from_stmt(stmt: &Stmt, source: &str) -> Indentation { + let line_start = Locator::new(source).line_start(stmt.start()); + + let mut indentation = 0u32; + for c in source[TextRange::new(line_start, stmt.start())].chars() { + if is_indent_whitespace(c) { + indentation += 1; + } else { + break; + } + } + + Indentation(indentation) + } + + fn trim_indent(self, ranged: impl Ranged, source: &str) -> TextRange { + let range = ranged.range(); + let mut start_offset = TextSize::default(); + + for c in source[range].chars().take(self.0 as usize) { + if is_indent_whitespace(c) { + start_offset += TextSize::new(1); + } else { + break; + } + } + + TextRange::new(range.start() + start_offset, range.end()) + } +} + +/// Returns `true` for a space or tab character. +/// +/// This is different than [`is_python_whitespace`] in that it returns `false` for a form feed character. +/// Form feed characters are excluded because they should be preserved in the suppressed output. +const fn is_indent_whitespace(c: char) -> bool { + matches!(c, ' ' | '\t') +} + +/// Formats a verbatim range where the top-level nodes are statements (or statement-level comments). +/// +/// Formats each statement as written in the source code, but adds the right indentation to match +/// the indentation of formatted statements: +/// +/// ```python +/// def test(): +/// print("formatted") +/// # fmt: off +/// ( +/// not_formatted + b +/// ) +/// # fmt: on +/// ``` +/// +/// Gets formatted as +/// +/// ```python +/// def test(): +/// print("formatted") +/// # fmt: off +/// ( +/// not_formatted + b +/// ) +/// # fmt: on +/// ``` +/// +/// Notice how the `not_formatted + b` expression statement gets the same indentation as the `print` statement above, +/// but the indentation of the expression remains unchanged. It changes the indentation to: +/// * Prevent syntax errors because of different indentation levels between formatted and suppressed statements. +/// * Align with the `fmt: skip` where statements are indented as well, but inner expressions are formatted as is. +struct FormatVerbatimStatementRange { + verbatim_range: TextRange, + indentation: Indentation, +} + +impl Format> for FormatVerbatimStatementRange { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let lexer = lex_starts_at( + &f.context().source()[self.verbatim_range], + Mode::Module, + self.verbatim_range.start(), + ); + + let logical_lines = LogicalLinesIter::new(lexer, self.verbatim_range); + let mut first = true; + + for logical_line in logical_lines { + let logical_line = logical_line?; + + let trimmed_line_range = self + .indentation + .trim_indent(&logical_line, f.context().source()); + + // A line without any content, write an empty line, except for the first or last (indent only) line. + if trimmed_line_range.is_empty() { + if logical_line.has_trailing_newline { + if first { + hard_line_break().fmt(f)?; + } else { + empty_line().fmt(f)?; + } + } + } else { + // Non empty line, write the text of the line + verbatim_text(trimmed_line_range, logical_line.contains_newlines).fmt(f)?; + + // Write the line separator that terminates the line, except if it is the last line (that isn't separated by a hard line break). + if logical_line.has_trailing_newline { + // Insert an empty line if the text is non-empty but all characters have a width of zero. + // This is necessary to work around the fact that the Printer omits hard line breaks if the line width is 0. + // The alternative is to "fix" the printer and explicitly track the width and whether the line is empty. + // There's currently no use case for zero-width content outside of the verbatim context (and, form feeds are a Python specific speciality). + // It, therefore, feels wrong to add additional complexity to the very hot `Printer::print_char` function, + // to work around this special case. Therefore, work around the Printer behavior here, in the cold verbatim-formatting. + if f.context().source()[trimmed_line_range].width() == 0 { + empty_line().fmt(f)?; + } else { + hard_line_break().fmt(f)?; + } + } + } + + first = false; + } + + Ok(()) + } +} + +struct LogicalLinesIter { + lexer: I, + // The end of the last logical line + last_line_end: TextSize, + // The position where the content to lex ends. + content_end: TextSize, +} + +impl LogicalLinesIter { + fn new(lexer: I, verbatim_range: TextRange) -> Self { + Self { + lexer, + last_line_end: verbatim_range.start(), + content_end: verbatim_range.end(), + } + } +} + +impl Iterator for LogicalLinesIter +where + I: Iterator, +{ + type Item = FormatResult; + + fn next(&mut self) -> Option { + let mut parens = 0u32; + let mut contains_newlines = ContainsNewlines::No; + + let (content_end, full_end) = loop { + match self.lexer.next() { + Some(Ok((token, range))) => match token { + Tok::Newline => break (range.start(), range.end()), + // Ignore if inside an expression + Tok::NonLogicalNewline if parens == 0 => break (range.start(), range.end()), + Tok::NonLogicalNewline => { + contains_newlines = ContainsNewlines::Yes; + } + Tok::Lbrace | Tok::Lpar | Tok::Lsqb => { + parens = parens.saturating_add(1); + } + Tok::Rbrace | Tok::Rpar | Tok::Rsqb => { + parens = parens.saturating_sub(1); + } + Tok::String { value, .. } if value.contains(['\n', '\r']) => { + contains_newlines = ContainsNewlines::Yes; + } + _ => {} + }, + None => { + // Returns any content that comes after the last newline. This is mainly whitespace + // or characters that the `Lexer` skips, like a form-feed character. + return if self.last_line_end < self.content_end { + let content_start = self.last_line_end; + self.last_line_end = self.content_end; + Some(Ok(LogicalLine { + content_range: TextRange::new(content_start, self.content_end), + contains_newlines: ContainsNewlines::No, + has_trailing_newline: false, + })) + } else { + None + }; + } + Some(Err(_)) => { + return Some(Err(FormatError::syntax_error( + "Unexpected token when lexing verbatim statement range.", + ))) + } + } + }; + + let line_start = self.last_line_end; + self.last_line_end = full_end; + + Some(Ok(LogicalLine { + content_range: TextRange::new(line_start, content_end), + contains_newlines, + has_trailing_newline: true, + })) + } +} + +impl FusedIterator for LogicalLinesIter where I: Iterator {} + +/// A logical line or a comment (or form feed only) line +struct LogicalLine { + /// The range of this lines content (excluding the trailing newline) + content_range: TextRange, + /// Whether the content in `content_range` contains any newlines. + contains_newlines: ContainsNewlines, + /// Does this logical line have a trailing newline or does it just happen to be the last line. + has_trailing_newline: bool, +} + +impl Ranged for LogicalLine { + fn range(&self) -> TextRange { + self.content_range + } +} + +struct VerbatimText { + verbatim_range: TextRange, + contains_newlines: ContainsNewlines, +} + +fn verbatim_text(item: T, contains_newlines: ContainsNewlines) -> VerbatimText +where + T: Ranged, +{ + VerbatimText { + verbatim_range: item.range(), + contains_newlines, + } +} + +impl Format> for VerbatimText { + fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { + f.write_element(FormatElement::Tag(Tag::StartVerbatim( + tag::VerbatimKind::Verbatim { + length: self.verbatim_range.len(), + }, + ))); + + match normalize_newlines(f.context().locator().slice(self.verbatim_range), ['\r']) { + Cow::Borrowed(_) => { + write!( + f, + [source_text_slice( + self.verbatim_range, + self.contains_newlines + )] + )?; + } + Cow::Owned(cleaned) => { + write!( + f, + [ + dynamic_text(&cleaned, Some(self.verbatim_range.start())), + source_position(self.verbatim_range.end()) + ] + )?; + } + } + + f.write_element(FormatElement::Tag(Tag::EndVerbatim)); + Ok(()) + } +} + +/// Disables formatting for `node` and instead uses the same formatting as the node has in source. +/// +/// The `node` gets indented as any formatted node to avoid syntax errors when the indentation string changes (e.g. from 2 spaces to 4). +/// The `node`s leading and trailing comments are formatted as usual, except if they fall into the suppressed node's range. +#[cold] +pub(crate) fn suppressed_node<'a, N>(node: N) -> FormatSuppressedNode<'a> +where + N: Into>, +{ + FormatSuppressedNode { node: node.into() } +} + +pub(crate) struct FormatSuppressedNode<'a> { + node: AnyNodeRef<'a>, +} + +impl Format> for FormatSuppressedNode<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let comments = f.context().comments().clone(); + let node_comments = comments.leading_dangling_trailing(self.node); + + // Mark all comments as formatted that fall into the node range + for comment in node_comments.leading { + if comment.start() > self.node.start() { + comment.mark_formatted(); + } + } + + for comment in node_comments.trailing { + if comment.start() < self.node.end() { + comment.mark_formatted(); + } + } + + comments.mark_verbatim_node_comments_formatted(self.node); + + // Write the outer comments and format the node as verbatim + write!( + f, + [ + leading_comments(node_comments.leading), + verbatim_text(self.node, ContainsNewlines::Detect), + trailing_comments(node_comments.trailing) + ] + ) + } +} + +#[cold] +pub(crate) fn write_suppressed_clause_header( + header: ClauseHeader, + f: &mut PyFormatter, +) -> FormatResult<()> { + // Write the outer comments and format the node as verbatim + write!( + f, + [verbatim_text( + header.range(f.context().source())?, + ContainsNewlines::Detect + )] + )?; + + let comments = f.context().comments(); + header.visit(&mut |child| { + for comment in comments.leading_trailing(child) { + comment.mark_formatted(); + } + comments.mark_verbatim_node_comments_formatted(child); + }); + + Ok(()) +} diff --git a/crates/ruff_python_formatter/tests/fixtures.rs b/crates/ruff_python_formatter/tests/fixtures.rs index 5d9be66a41ab2..1991b838f4760 100644 --- a/crates/ruff_python_formatter/tests/fixtures.rs +++ b/crates/ruff_python_formatter/tests/fixtures.rs @@ -17,7 +17,7 @@ fn black_compatibility() { let reader = BufReader::new(options_file); serde_json::from_reader(reader).expect("Options to be a valid Json file") } else { - PyFormatOptions::default() + PyFormatOptions::from_extension(input_path) }; let printed = format_module(&content, options.clone()).unwrap_or_else(|err| { @@ -106,11 +106,11 @@ fn format() { let test_file = |input_path: &Path| { let content = fs::read_to_string(input_path).unwrap(); - let options = PyFormatOptions::default(); + let options = PyFormatOptions::from_extension(input_path); let printed = format_module(&content, options.clone()).expect("Formatting to succeed"); let formatted_code = printed.as_code(); - ensure_stability_when_formatting_twice(formatted_code, options, input_path); + ensure_stability_when_formatting_twice(formatted_code, options.clone(), input_path); let mut snapshot = format!("## Input\n{}", CodeFrame::new("py", &content)); @@ -139,7 +139,6 @@ fn format() { .unwrap(); } } else { - let options = PyFormatOptions::default(); let printed = format_module(&content, options.clone()).expect("Formatting to succeed"); let formatted_code = printed.as_code(); @@ -162,7 +161,11 @@ fn format() { }); }; - insta::glob!("../resources", "test/fixtures/ruff/**/*.py", test_file); + insta::glob!( + "../resources", + "test/fixtures/ruff/**/*.{py,pyi}", + test_file + ); } /// Format another time and make sure that there are no changes anymore diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__docstring_no_string_normalization.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__docstring_no_string_normalization.py.snap index 80c7ba60ec495..0b680fd94cdb0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__docstring_no_string_normalization.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__docstring_no_string_normalization.py.snap @@ -135,7 +135,7 @@ def multiline_backslash_3(): ```diff --- Black +++ Ruff -@@ -1,73 +1,75 @@ +@@ -1,24 +1,24 @@ class ALonelyClass: - ''' + """ @@ -167,96 +167,7 @@ def multiline_backslash_3(): pass - def foo(): -- """This is a docstring with -- some lines of text here -- """ -+ """This is a docstring with -+ some lines of text here -+ """ - return - - - def baz(): - '''"This" is a string with some -- embedded "quotes"''' -+ embedded "quotes"''' - return - - - def poit(): - """ -- Lorem ipsum dolor sit amet. -+ Lorem ipsum dolor sit amet. - -- Consectetur adipiscing elit: -- - sed do eiusmod tempor incididunt ut labore -- - dolore magna aliqua -- - enim ad minim veniam -- - quis nostrud exercitation ullamco laboris nisi -- - aliquip ex ea commodo consequat -- """ -+ Consectetur adipiscing elit: -+ - sed do eiusmod tempor incididunt ut labore -+ - dolore magna aliqua -+ - enim ad minim veniam -+ - quis nostrud exercitation ullamco laboris nisi -+ - aliquip ex ea commodo consequat -+ """ - pass - - - def under_indent(): - """ -- These lines are indented in a way that does not -- make sense. -- """ -+ These lines are indented in a way that does not -+make sense. -+ """ - pass - - - def over_indent(): - """ -- This has a shallow indent -- - But some lines are deeper -- - And the closing quote is too deep -+ This has a shallow indent -+ - But some lines are deeper -+ - And the closing quote is too deep - """ - pass - - - def single_line(): -- """But with a newline after it!""" -+ """But with a newline after it! -+ -+ """ - pass - - -@@ -83,41 +85,41 @@ - - def and_that(): - """ -- "hey yah" """ -+ "hey yah" """ - - - def and_this(): -- ''' -- "hey yah"''' -+ ''' -+ "hey yah"''' - - - def believe_it_or_not_this_is_in_the_py_stdlib(): -- ''' -- "hey yah"''' -+ ''' -+"hey yah"''' +@@ -97,27 +97,27 @@ def shockingly_the_quotes_are_normalized_v2(): @@ -285,14 +196,14 @@ def multiline_backslash_3(): - ''' - hey there \ ''' + """ -+ hey there \ """ ++ hey there \ """ def multiline_backslash_3(): - ''' - already escaped \\''' + """ -+ already escaped \\ """ ++ already escaped \\""" ``` ## Ruff Output @@ -323,53 +234,51 @@ def shockingly_the_quotes_are_normalized(): def foo(): - """This is a docstring with - some lines of text here - """ + """This is a docstring with + some lines of text here + """ return def baz(): '''"This" is a string with some - embedded "quotes"''' + embedded "quotes"''' return def poit(): """ - Lorem ipsum dolor sit amet. + Lorem ipsum dolor sit amet. - Consectetur adipiscing elit: - - sed do eiusmod tempor incididunt ut labore - - dolore magna aliqua - - enim ad minim veniam - - quis nostrud exercitation ullamco laboris nisi - - aliquip ex ea commodo consequat - """ + Consectetur adipiscing elit: + - sed do eiusmod tempor incididunt ut labore + - dolore magna aliqua + - enim ad minim veniam + - quis nostrud exercitation ullamco laboris nisi + - aliquip ex ea commodo consequat + """ pass def under_indent(): """ - These lines are indented in a way that does not -make sense. - """ + These lines are indented in a way that does not + make sense. + """ pass def over_indent(): """ - This has a shallow indent - - But some lines are deeper - - And the closing quote is too deep + This has a shallow indent + - But some lines are deeper + - And the closing quote is too deep """ pass def single_line(): - """But with a newline after it! - - """ + """But with a newline after it!""" pass @@ -385,17 +294,17 @@ def that(): def and_that(): """ - "hey yah" """ + "hey yah" """ def and_this(): - ''' - "hey yah"''' + ''' + "hey yah"''' def believe_it_or_not_this_is_in_the_py_stdlib(): - ''' -"hey yah"''' + ''' + "hey yah"''' def shockingly_the_quotes_are_normalized_v2(): @@ -417,12 +326,12 @@ def multiline_backslash_1(): def multiline_backslash_2(): """ - hey there \ """ + hey there \ """ def multiline_backslash_3(): """ - already escaped \\ """ + already escaped \\""" ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__long_strings_flag_disabled.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__long_strings_flag_disabled.py.snap index 6e2a6ac805316..8be3c1f3eab42 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__long_strings_flag_disabled.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__long_strings_flag_disabled.py.snap @@ -304,23 +304,7 @@ long_unmergable_string_with_pragma = ( ```diff --- Black +++ Ruff -@@ -143,9 +143,13 @@ - ) - ) - --fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one." -+fstring = ( -+ f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one." -+) - --fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever." -+fstring_with_no_fexprs = ( -+ f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever." -+) - - comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top. - -@@ -165,13 +169,9 @@ +@@ -165,13 +165,9 @@ triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched.""" @@ -336,7 +320,7 @@ long_unmergable_string_with_pragma = ( "formatting" ) -@@ -221,8 +221,8 @@ +@@ -221,8 +217,8 @@ func_with_bad_comma( ( "This is a really long string argument to a function that has a trailing comma" @@ -347,17 +331,6 @@ long_unmergable_string_with_pragma = ( ) func_with_bad_parens_that_wont_fit_in_one_line( -@@ -274,7 +274,9 @@ - yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three." - - --x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four." -+x = ( -+ f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four." -+) - - long_unmergable_string_with_pragma = ( - "This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore ``` ## Ruff Output @@ -508,13 +481,9 @@ old_fmt_string3 = ( ) ) -fstring = ( - f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one." -) +fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one." -fstring_with_no_fexprs = ( - f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever." -) +fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever." comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top. @@ -639,9 +608,7 @@ def foo(): yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three." -x = ( - f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four." -) +x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four." long_unmergable_string_with_pragma = ( "This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap index ce5a833fd20b5..1c7fe97abe929 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap @@ -156,180 +156,63 @@ match x: ```diff --- Black +++ Ruff -@@ -1,144 +1,60 @@ - # Cases sampled from Lib/test/test_patma.py - - # case black_test_patma_098 --match x: -- case -0j: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch +@@ -6,7 +6,7 @@ + y = 0 # case black_test_patma_142 --match x: + match x: - case bytes(z): -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + y = 0 # case black_test_patma_073 --match x: -- case 0 if 0: -- y = 0 -- case 0 if 1: -- y = 1 -+NOT_YET_IMPLEMENTED_StmtMatch + match x: +@@ -16,11 +16,11 @@ + y = 1 # case black_test_patma_006 --match 3: + match 3: - case 0 | 1 | 2 | 3: -- x = True -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + x = True # case black_test_patma_049 --match x: + match x: - case [0, 1] | [1, 0]: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 0 # case black_check_sequence_then_mapping --match x: -- case [*_]: -- return "seq" -- case {}: -- return "map" -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_035 --match x: -- case {0: [1, 2, {}]}: -- y = 0 + match x: +@@ -32,7 +32,7 @@ + match x: + case {0: [1, 2, {}]}: + y = 0 - case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: -- y = 1 -- case []: -- y = 2 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_107 --match x: -- case 0.25 + 1.75j: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_097 --match x: -- case -0j: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 1 + case []: + y = 2 +@@ -46,7 +46,7 @@ + y = 0 # case black_test_patma_007 --match 4: + match 4: - case 0 | 1 | 2 | 3: -- x = True -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + x = True # case black_test_patma_154 --match x: -- case 0 if x: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_134 --match x: -- case {1: 0}: -- y = 0 -- case {0: 0}: -- y = 1 -- case {**z}: -- y = 2 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_185 --match Seq(): -- case [*_]: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_063 --match x: -- case 1: -- y = 0 -- case 1: -- y = 1 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_248 --match x: -- case {"foo": bar}: -- y = bar -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_019 --match (0, 1, 2): -- case [0, 1, *x, 2]: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_052 --match x: -- case [0]: -- y = 0 -- case [1, 0] if (x := x[:0]): -- y = 1 -- case [1, 0]: -- y = 2 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_191 --match w: -- case [x, y, *_]: -- z = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_110 --match x: -- case -0.25 - 1.75j: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_151 --match (x,): -- case [y]: -- z = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_114 --match x: -- case A.B.C.D: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_232 --match x: -- case None: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_058 --match x: -- case 0: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_233 --match x: -- case False: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_078 --match x: -- case []: -- y = 0 -- case [""]: -- y = 1 -- case "": -- y = 2 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_156 --match x: -- case z: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch - # case black_test_patma_189 --match w: -- case [x, y, *rest]: -- z = 0 -+NOT_YET_IMPLEMENTED_StmtMatch + match x: +@@ -132,13 +132,13 @@ + z = 0 # case black_test_patma_042 --match x: + match x: - case (0 as z) | (1 as z) | (2 as z) if z == x % 2: -- y = 0 -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y) if z == x % 2: + y = 0 # case black_test_patma_034 --match x: -- case {0: [1, 2, {}]}: -- y = 0 + match x: + case {0: [1, 2, {}]}: + y = 0 - case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}: -- y = 1 -- case []: -- y = 2 -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 1 + case []: + y = 2 ``` ## Ruff Output @@ -338,63 +221,147 @@ match x: # Cases sampled from Lib/test/test_patma.py # case black_test_patma_098 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case -0j: + y = 0 # case black_test_patma_142 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + y = 0 # case black_test_patma_073 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case 0 if 0: + y = 0 + case 0 if 1: + y = 1 # case black_test_patma_006 -NOT_YET_IMPLEMENTED_StmtMatch +match 3: + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + x = True # case black_test_patma_049 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 0 # case black_check_sequence_then_mapping -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case [*_]: + return "seq" + case {}: + return "map" # case black_test_patma_035 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case {0: [1, 2, {}]}: + y = 0 + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 1 + case []: + y = 2 # case black_test_patma_107 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case 0.25 + 1.75j: + y = 0 # case black_test_patma_097 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case -0j: + y = 0 # case black_test_patma_007 -NOT_YET_IMPLEMENTED_StmtMatch +match 4: + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + x = True # case black_test_patma_154 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case 0 if x: + y = 0 # case black_test_patma_134 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case {1: 0}: + y = 0 + case {0: 0}: + y = 1 + case {**z}: + y = 2 # case black_test_patma_185 -NOT_YET_IMPLEMENTED_StmtMatch +match Seq(): + case [*_]: + y = 0 # case black_test_patma_063 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case 1: + y = 0 + case 1: + y = 1 # case black_test_patma_248 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case {"foo": bar}: + y = bar # case black_test_patma_019 -NOT_YET_IMPLEMENTED_StmtMatch +match (0, 1, 2): + case [0, 1, *x, 2]: + y = 0 # case black_test_patma_052 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case [0]: + y = 0 + case [1, 0] if (x := x[:0]): + y = 1 + case [1, 0]: + y = 2 # case black_test_patma_191 -NOT_YET_IMPLEMENTED_StmtMatch +match w: + case [x, y, *_]: + z = 0 # case black_test_patma_110 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case -0.25 - 1.75j: + y = 0 # case black_test_patma_151 -NOT_YET_IMPLEMENTED_StmtMatch +match (x,): + case [y]: + z = 0 # case black_test_patma_114 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case A.B.C.D: + y = 0 # case black_test_patma_232 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case None: + y = 0 # case black_test_patma_058 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case 0: + y = 0 # case black_test_patma_233 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case False: + y = 0 # case black_test_patma_078 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case []: + y = 0 + case [""]: + y = 1 + case "": + y = 2 # case black_test_patma_156 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case z: + y = 0 # case black_test_patma_189 -NOT_YET_IMPLEMENTED_StmtMatch +match w: + case [x, y, *rest]: + z = 0 # case black_test_patma_042 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y) if z == x % 2: + y = 0 # case black_test_patma_034 -NOT_YET_IMPLEMENTED_StmtMatch +match x: + case {0: [1, 2, {}]}: + y = 0 + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + y = 1 + case []: + y = 2 ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap index 23dd576815230..e048f251a4ed6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap @@ -131,139 +131,113 @@ match bar1: ```diff --- Black +++ Ruff -@@ -1,119 +1,43 @@ - import match - --match something: -- case [a as b]: -- print(b) -- case [a as b, c, d, e as f]: -- print(f) +@@ -5,9 +5,9 @@ + print(b) + case [a as b, c, d, e as f]: + print(f) - case Point(a as b): -- print(b) ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(b) - case Point(int() as x, int() as y): -- print(x, y) -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(x, y) - match = 1 +@@ -15,7 +15,7 @@ case: int = re.match(something) --match re.match(case): + match re.match(case): - case type("match", match): -- pass -- case match: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch - ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass + case match: + pass +@@ -23,7 +23,7 @@ def func(match: case, case: match) -> case: -- match Something(): + match Something(): - case func(match, case): -- ... -- case another: -- ... -+ NOT_YET_IMPLEMENTED_StmtMatch - - --match maybe, multiple: -- case perhaps, 5: -- pass ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + ... + case another: + ... +@@ -32,14 +32,23 @@ + match maybe, multiple: + case perhaps, 5: + pass - case perhaps, 6,: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case ( ++ perhaps, ++ 6, ++ ): + pass -match more := (than, one), indeed,: -- case _, (5, 6): -- pass ++match ( ++ more := (than, one), ++ indeed, ++): + case _, (5, 6): + pass - case [[5], (6)], [7],: -- pass -- case _: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch - - --match a, *b, c: -- case [*_]: -- assert "seq" == _ -- case {}: -- assert "map" == b -+NOT_YET_IMPLEMENTED_StmtMatch - - --match match( -- case, -- match( -- match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match -- ), -- case, --): ++ case [ ++ [[5], (6)], ++ [7], ++ ]: + pass + case _: + pass +@@ -59,12 +68,7 @@ + ), + case, + ): - case case( - match=case, - case=re.match( - loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - ), - ): -- pass -+NOT_YET_IMPLEMENTED_StmtMatch - -- case [a as match]: -- pass - -- case case: -- pass -- -- --match match: -- case case: -- pass -- -+NOT_YET_IMPLEMENTED_StmtMatch - --match a, *b(), c: -- case d, *f, g: -- pass ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass -- --match something: -- case { -- "key": key as key_1, + case [a as match]: +@@ -87,10 +91,10 @@ + match something: + case { + "key": key as key_1, - "password": PASS.ONE | PASS.TWO | PASS.THREE as password, -- }: -- pass ++ "password": NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as password, + }: + pass - case {"maybe": something(complicated as this) as that}: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case {"maybe": NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0) as that}: + pass --match something: -- case 1 as a: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch - -- case 2 as b, 3 as c: -- pass +@@ -101,19 +105,17 @@ + case 2 as b, 3 as c: + pass - case 4 as d, (5 as e), (6 | 7 as g), *h: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case 4 as d, (5 as e), (NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g), *h: + pass --match bar1: + match bar1: - case Foo(aa=Callable() as aa, bb=int()): -- print(bar1.aa, bar1.bb) -- case _: -- print("no match", "\n") -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(bar1.aa, bar1.bb) + case _: + print("no match", "\n") --match bar1: + match bar1: - case Foo( - normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u - ): -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass ``` ## Ruff Output @@ -271,47 +245,125 @@ match bar1: ```py import match -NOT_YET_IMPLEMENTED_StmtMatch +match something: + case [a as b]: + print(b) + case [a as b, c, d, e as f]: + print(f) + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(b) + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(x, y) match = 1 case: int = re.match(something) -NOT_YET_IMPLEMENTED_StmtMatch +match re.match(case): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass + case match: + pass def func(match: case, case: match) -> case: - NOT_YET_IMPLEMENTED_StmtMatch + match Something(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + ... + case another: + ... -NOT_YET_IMPLEMENTED_StmtMatch +match maybe, multiple: + case perhaps, 5: + pass + case ( + perhaps, + 6, + ): + pass -NOT_YET_IMPLEMENTED_StmtMatch +match ( + more := (than, one), + indeed, +): + case _, (5, 6): + pass + case [ + [[5], (6)], + [7], + ]: + pass + case _: + pass -NOT_YET_IMPLEMENTED_StmtMatch +match a, *b, c: + case [*_]: + assert "seq" == _ + case {}: + assert "map" == b -NOT_YET_IMPLEMENTED_StmtMatch +match match( + case, + match( + match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match + ), + case, +): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass + case [a as match]: + pass -NOT_YET_IMPLEMENTED_StmtMatch + case case: + pass -NOT_YET_IMPLEMENTED_StmtMatch +match match: + case case: + pass -NOT_YET_IMPLEMENTED_StmtMatch +match a, *b(), c: + case d, *f, g: + pass -NOT_YET_IMPLEMENTED_StmtMatch +match something: + case { + "key": key as key_1, + "password": NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as password, + }: + pass + case {"maybe": NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0) as that}: + pass + + +match something: + case 1 as a: + pass + + case 2 as b, 3 as c: + pass + case 4 as d, (5 as e), (NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g), *h: + pass -NOT_YET_IMPLEMENTED_StmtMatch + +match bar1: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(bar1.aa, bar1.bb) + case _: + print("no match", "\n") -NOT_YET_IMPLEMENTED_StmtMatch +match bar1: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap index 6049e7897bebb..74ef3ffc47899 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap @@ -119,49 +119,15 @@ with match() as match: ```diff --- Black +++ Ruff -@@ -23,11 +23,7 @@ - pygram.python_grammar, - ] - -- match match: -- case case: -- match match: -- case case: -- pass -+ NOT_YET_IMPLEMENTED_StmtMatch - - if all(version.is_python2() for version in target_versions): - # Python 2-only code, so try Python 2 grammars. -@@ -45,9 +41,7 @@ - +@@ -46,7 +46,7 @@ def test_patma_139(self): x = False -- match x: + match x: - case bool(z): -- y = 0 -+ NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + y = 0 self.assertIs(x, False) self.assertEqual(y, 0) - self.assertIs(z, x) -@@ -72,16 +66,12 @@ - def test_patma_155(self): - x = 0 - y = None -- match x: -- case 1e1000: -- y = 0 -+ NOT_YET_IMPLEMENTED_StmtMatch - self.assertEqual(x, 0) - self.assertIs(y, None) - - x = range(3) -- match x: -- case [y, case as x, z]: -- w = 0 -+ NOT_YET_IMPLEMENTED_StmtMatch - - # At least one of the above branches must have been taken, because every Python - # version has exactly one of the two 'ASYNC_*' flags ``` ## Ruff Output @@ -192,7 +158,11 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: pygram.python_grammar, ] - NOT_YET_IMPLEMENTED_StmtMatch + match match: + case case: + match match: + case case: + pass if all(version.is_python2() for version in target_versions): # Python 2-only code, so try Python 2 grammars. @@ -210,7 +180,9 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: def test_patma_139(self): x = False - NOT_YET_IMPLEMENTED_StmtMatch + match x: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + y = 0 self.assertIs(x, False) self.assertEqual(y, 0) self.assertIs(z, x) @@ -235,12 +207,16 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: def test_patma_155(self): x = 0 y = None - NOT_YET_IMPLEMENTED_StmtMatch + match x: + case 1e1000: + y = 0 self.assertEqual(x, 0) self.assertIs(y, None) x = range(3) - NOT_YET_IMPLEMENTED_StmtMatch + match x: + case [y, case as x, z]: + w = 0 # At least one of the above branches must have been taken, because every Python # version has exactly one of the two 'ASYNC_*' flags diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap index a165da5f84fff..edbd357b65533 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap @@ -104,111 +104,73 @@ def where_is(point): ```diff --- Black +++ Ruff -@@ -1,92 +1,27 @@ - # Cases sampled from PEP 636 examples +@@ -39,18 +39,18 @@ + print(f"Sorry, I couldn't understand {command!r}") --match command.split(): -- case [action, obj]: -- ... # interpret action, obj -+NOT_YET_IMPLEMENTED_StmtMatch - --match command.split(): -- case [action]: -- ... # interpret single-verb action -- case [action, obj]: -- ... # interpret action, obj -+NOT_YET_IMPLEMENTED_StmtMatch - --match command.split(): -- case ["quit"]: -- print("Goodbye!") -- quit_game() -- case ["look"]: -- current_room.describe() -- case ["get", obj]: -- character.get(obj, current_room) -- case ["go", direction]: -- current_room = current_room.neighbor(direction) -- # The rest of your commands go here -+NOT_YET_IMPLEMENTED_StmtMatch - --match command.split(): -- case ["drop", *objects]: -- for obj in objects: -- character.drop(obj, current_room) -- # The rest of your commands go here -+NOT_YET_IMPLEMENTED_StmtMatch - --match command.split(): -- case ["quit"]: -- pass -- case ["go", direction]: -- print("Going:", direction) -- case ["drop", *objects]: -- print("Dropping: ", *objects) -- case _: -- print(f"Sorry, I couldn't understand {command!r}") -+NOT_YET_IMPLEMENTED_StmtMatch - --match command.split(): + match command.split(): - case ["north"] | ["go", "north"]: -- current_room = current_room.neighbor("north") ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + current_room = current_room.neighbor("north") - case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]: -- ... # Code for picking up the given object -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + ... # Code for picking up the given object --match command.split(): + match command.split(): - case ["go", ("north" | "south" | "east" | "west")]: -- current_room = current_room.neighbor(...) -- # how do I know which direction to go? -+NOT_YET_IMPLEMENTED_StmtMatch ++ case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y))]: + current_room = current_room.neighbor(...) + # how do I know which direction to go? --match command.split(): + match command.split(): - case ["go", ("north" | "south" | "east" | "west") as direction]: -- current_room = current_room.neighbor(direction) -+NOT_YET_IMPLEMENTED_StmtMatch ++ case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y)) as direction]: + current_room = current_room.neighbor(direction) --match command.split(): -- case ["go", direction] if direction in current_room.exits: -- current_room = current_room.neighbor(direction) -- case ["go", _]: -- print("Sorry, you can't go that way") -+NOT_YET_IMPLEMENTED_StmtMatch + match command.split(): +@@ -60,33 +60,33 @@ + print("Sorry, you can't go that way") --match event.get(): + match event.get(): - case Click(position=(x, y)): -- handle_click_at(x, y) ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + handle_click_at(x, y) - case KeyPress(key_name="Q") | Quit(): -- game.quit() ++ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + game.quit() - case KeyPress(key_name="up arrow"): -- game.go_north() ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + game.go_north() - case KeyPress(): -- pass # Ignore other keystrokes -- case other_event: -- raise ValueError(f"Unrecognized event: {other_event}") -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass # Ignore other keystrokes + case other_event: + raise ValueError(f"Unrecognized event: {other_event}") --match event.get(): + match event.get(): - case Click((x, y), button=Button.LEFT): # This is a left click -- handle_click_at(x, y) ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): # This is a left click + handle_click_at(x, y) - case Click(): -- pass # ignore other clicks -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass # ignore other clicks def where_is(point): -- match point: + match point: - case Point(x=0, y=0): -- print("Origin") ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print("Origin") - case Point(x=0, y=y): -- print(f"Y={y}") ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"Y={y}") - case Point(x=x, y=0): -- print(f"X={x}") ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"X={x}") - case Point(): -- print("Somewhere else") -- case _: -- print("Not a point") -+ NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print("Somewhere else") + case _: + print("Not a point") ``` ## Ruff Output @@ -216,31 +178,96 @@ def where_is(point): ```py # Cases sampled from PEP 636 examples -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case [action, obj]: + ... # interpret action, obj -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case [action]: + ... # interpret single-verb action + case [action, obj]: + ... # interpret action, obj -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["quit"]: + print("Goodbye!") + quit_game() + case ["look"]: + current_room.describe() + case ["get", obj]: + character.get(obj, current_room) + case ["go", direction]: + current_room = current_room.neighbor(direction) + # The rest of your commands go here -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["drop", *objects]: + for obj in objects: + character.drop(obj, current_room) + # The rest of your commands go here -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["quit"]: + pass + case ["go", direction]: + print("Going:", direction) + case ["drop", *objects]: + print("Dropping: ", *objects) + case _: + print(f"Sorry, I couldn't understand {command!r}") -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + current_room = current_room.neighbor("north") + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + ... # Code for picking up the given object -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y))]: + current_room = current_room.neighbor(...) + # how do I know which direction to go? -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y)) as direction]: + current_room = current_room.neighbor(direction) -NOT_YET_IMPLEMENTED_StmtMatch +match command.split(): + case ["go", direction] if direction in current_room.exits: + current_room = current_room.neighbor(direction) + case ["go", _]: + print("Sorry, you can't go that way") -NOT_YET_IMPLEMENTED_StmtMatch +match event.get(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + handle_click_at(x, y) + case NOT_YET_IMPLEMENTED_PatternMatchOf | (y): + game.quit() + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + game.go_north() + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass # Ignore other keystrokes + case other_event: + raise ValueError(f"Unrecognized event: {other_event}") -NOT_YET_IMPLEMENTED_StmtMatch +match event.get(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): # This is a left click + handle_click_at(x, y) + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass # ignore other clicks def where_is(point): - NOT_YET_IMPLEMENTED_StmtMatch + match point: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print("Origin") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"Y={y}") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"X={x}") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print("Somewhere else") + case _: + print("Not a point") ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap index 56fe93fb726bf..3f8e3b8febe2e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap @@ -65,22 +65,24 @@ match match( ```diff --- Black +++ Ruff -@@ -1,35 +1,24 @@ --match something: +@@ -1,35 +1,34 @@ + match something: - case b(): -- print(1 + 1) ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(1 + 1) - case c( - very_complex=True, perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1 - ): -- print(1) ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(1) - case c( - very_complex=True, - perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1, - ): -- print(2) -- case a: -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(2) + case a: + pass -match(arg) # comment +match( @@ -106,18 +108,26 @@ match match( + something # fast +) re.match() --match match(): + match match(): - case case( - arg, # comment - ): -- pass -+NOT_YET_IMPLEMENTED_StmtMatch ++ case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass ``` ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtMatch +match something: + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(1 + 1) + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(1) + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(2) + case a: + pass match( arg # comment @@ -140,7 +150,9 @@ re.match( something # fast ) re.match() -NOT_YET_IMPLEMENTED_StmtMatch +match match(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + pass ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__remove_newline_after_match.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__remove_newline_after_match.py.snap deleted file mode 100644 index 6099825e88f56..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__remove_newline_after_match.py.snap +++ /dev/null @@ -1,76 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_310/remove_newline_after_match.py ---- -## Input - -```py -def http_status(status): - - match status: - - case 400: - - return "Bad request" - - case 401: - - return "Unauthorized" - - case 403: - - return "Forbidden" - - case 404: - - return "Not found" -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,13 +1,2 @@ - def http_status(status): -- match status: -- case 400: -- return "Bad request" -- -- case 401: -- return "Unauthorized" -- -- case 403: -- return "Forbidden" -- -- case 404: -- return "Not found" -+ NOT_YET_IMPLEMENTED_StmtMatch -``` - -## Ruff Output - -```py -def http_status(status): - NOT_YET_IMPLEMENTED_StmtMatch -``` - -## Black Output - -```py -def http_status(status): - match status: - case 400: - return "Bad request" - - case 401: - return "Unauthorized" - - case 403: - return "Forbidden" - - case 404: - return "Not found" -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_aliases.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_aliases.py.snap deleted file mode 100644 index eaf6dc14e9aca..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_aliases.py.snap +++ /dev/null @@ -1,50 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_312/type_aliases.py ---- -## Input - -```py -type A=int -type Gen[T]=list[T] - -type = aliased -print(type(42)) -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,5 +1,5 @@ --type A = int --type Gen[T] = list[T] -+type NOT_YET_IMPLEMENTED_type_alias = int -+type NOT_YET_IMPLEMENTED_type_alias = int - - type = aliased - print(type(42)) -``` - -## Ruff Output - -```py -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int - -type = aliased -print(type(42)) -``` - -## Black Output - -```py -type A = int -type Gen[T] = list[T] - -type = aliased -print(type(42)) -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_params.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_params.py.snap deleted file mode 100644 index c49fd8fb31f31..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_312__type_params.py.snap +++ /dev/null @@ -1,159 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_312/type_params.py ---- -## Input - -```py -def func [T ](): pass -async def func [ T ] (): pass -class C[ T ] : pass - -def all_in[T : int,U : (bytes, str),* Ts,**P](): pass - -def really_long[WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine](): pass - -def even_longer[WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine: WhatIfItHadABound](): pass - -def it_gets_worse[WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine, ItCouldBeGenericOverMultipleTypeVars](): pass - -def magic[Trailing, Comma,](): pass -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,40 +1,30 @@ --def func[T](): -+def func(): - pass - - --async def func[T](): -+async def func(): - pass - - --class C[T]: -+class C: - pass - - --def all_in[T: int, U: (bytes, str), *Ts, **P](): -+def all_in(): - pass - - --def really_long[ -- WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine --](): -+def really_long(): - pass - - --def even_longer[ -- WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine: WhatIfItHadABound --](): -+def even_longer(): - pass - - --def it_gets_worse[ -- WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine, -- ItCouldBeGenericOverMultipleTypeVars, --](): -+def it_gets_worse(): - pass - - --def magic[ -- Trailing, -- Comma, --](): -+def magic(): - pass -``` - -## Ruff Output - -```py -def func(): - pass - - -async def func(): - pass - - -class C: - pass - - -def all_in(): - pass - - -def really_long(): - pass - - -def even_longer(): - pass - - -def it_gets_worse(): - pass - - -def magic(): - pass -``` - -## Black Output - -```py -def func[T](): - pass - - -async def func[T](): - pass - - -class C[T]: - pass - - -def all_in[T: int, U: (bytes, str), *Ts, **P](): - pass - - -def really_long[ - WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine -](): - pass - - -def even_longer[ - WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine: WhatIfItHadABound -](): - pass - - -def it_gets_worse[ - WhatIsTheLongestTypeVarNameYouCanThinkOfEnoughToMakeBlackSplitThisLine, - ItCouldBeGenericOverMultipleTypeVars, -](): - pass - - -def magic[ - Trailing, - Comma, -](): - pass -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_570.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_570.py.snap deleted file mode 100644 index b1326fc877605..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_570.py.snap +++ /dev/null @@ -1,168 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_570.py ---- -## Input - -```py -def positional_only_arg(a, /): - pass - - -def all_markers(a, b, /, c, d, *, e, f): - pass - - -def all_markers_with_args_and_kwargs( - a_long_one, - b_long_one, - /, - c_long_one, - d_long_one, - *args, - e_long_one, - f_long_one, - **kwargs, -): - pass - - -def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5): - pass - - -def long_one_with_long_parameter_names( - but_all_of_them, - are_positional_only, - arguments_mmmmkay, - so_this_is_only_valid_after, - three_point_eight, - /, -): - pass - - -lambda a, /: a - -lambda a, b, /, c, d, *, e, f: a - -lambda a, b, /, c, d, *args, e, f, **kwargs: args - -lambda a, b=1, /, c=2, d=3, *, e=4, f=5: 1 -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -35,7 +35,7 @@ - pass - - --lambda a, /: a -+lambda: a - - lambda a, b, /, c, d, *, e, f: a - -``` - -## Ruff Output - -```py -def positional_only_arg(a, /): - pass - - -def all_markers(a, b, /, c, d, *, e, f): - pass - - -def all_markers_with_args_and_kwargs( - a_long_one, - b_long_one, - /, - c_long_one, - d_long_one, - *args, - e_long_one, - f_long_one, - **kwargs, -): - pass - - -def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5): - pass - - -def long_one_with_long_parameter_names( - but_all_of_them, - are_positional_only, - arguments_mmmmkay, - so_this_is_only_valid_after, - three_point_eight, - /, -): - pass - - -lambda: a - -lambda a, b, /, c, d, *, e, f: a - -lambda a, b, /, c, d, *args, e, f, **kwargs: args - -lambda a, b=1, /, c=2, d=3, *, e=4, f=5: 1 -``` - -## Black Output - -```py -def positional_only_arg(a, /): - pass - - -def all_markers(a, b, /, c, d, *, e, f): - pass - - -def all_markers_with_args_and_kwargs( - a_long_one, - b_long_one, - /, - c_long_one, - d_long_one, - *args, - e_long_one, - f_long_one, - **kwargs, -): - pass - - -def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5): - pass - - -def long_one_with_long_parameter_names( - but_all_of_them, - are_positional_only, - arguments_mmmmkay, - so_this_is_only_valid_after, - three_point_eight, - /, -): - pass - - -lambda a, /: a - -lambda a, b, /, c, d, *, e, f: a - -lambda a, b, /, c, d, *args, e, f, **kwargs: args - -lambda a, b=1, /, c=2, d=3, *, e=4, f=5: 1 -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_572_remove_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_572_remove_parens.py.snap new file mode 100644 index 0000000000000..daea36ba7ec65 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_38__pep_572_remove_parens.py.snap @@ -0,0 +1,247 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py +--- +## Input + +```py +if (foo := 0): + pass + +if (foo := 1): + pass + +if (y := 5 + 5): + pass + +y = (x := 0) + +y += (x := 0) + +(y := 5 + 5) + +test: int = (test2 := 2) + +a, b = (test := (1, 2)) + +# see also https://github.com/psf/black/issues/2139 +assert (foo := 42 - 12) + +foo(x=(y := f(x))) + + +def foo(answer=(p := 42)): + ... + + +def foo2(answer: (p := 42) = 5): + ... + + +lambda: (x := 1) + +a[(x := 12)] +a[:(x := 13)] + +# we don't touch expressions in f-strings but if we do one day, don't break 'em +f'{(x:=10)}' + + +def a(): + return (x := 3) + await (b := 1) + yield (a := 2) + raise (c := 3) + +def this_is_so_dumb() -> (please := no): + pass + +async def await_the_walrus(): + with (x := y): + pass + + with (x := y) as z, (a := b) as c: + pass + + with (x := await y): + pass + + with (x := await a, y := await b): + pass + + with ((x := await a, y := await b)): + pass + + with (x := await a), (y := await b): + pass +``` + +## Black Differences + +```diff +--- Black ++++ Ruff +@@ -34,7 +34,7 @@ + lambda: (x := 1) + + a[(x := 12)] +-a[:(x := 13)] ++a[: (x := 13)] + + # we don't touch expressions in f-strings but if we do one day, don't break 'em + f"{(x:=10)}" +``` + +## Ruff Output + +```py +if foo := 0: + pass + +if foo := 1: + pass + +if y := 5 + 5: + pass + +y = (x := 0) + +y += (x := 0) + +(y := 5 + 5) + +test: int = (test2 := 2) + +a, b = (test := (1, 2)) + +# see also https://github.com/psf/black/issues/2139 +assert (foo := 42 - 12) + +foo(x=(y := f(x))) + + +def foo(answer=(p := 42)): + ... + + +def foo2(answer: (p := 42) = 5): + ... + + +lambda: (x := 1) + +a[(x := 12)] +a[: (x := 13)] + +# we don't touch expressions in f-strings but if we do one day, don't break 'em +f"{(x:=10)}" + + +def a(): + return (x := 3) + await (b := 1) + yield (a := 2) + raise (c := 3) + + +def this_is_so_dumb() -> (please := no): + pass + + +async def await_the_walrus(): + with (x := y): + pass + + with (x := y) as z, (a := b) as c: + pass + + with (x := await y): + pass + + with (x := await a, y := await b): + pass + + with (x := await a, y := await b): + pass + + with (x := await a), (y := await b): + pass +``` + +## Black Output + +```py +if foo := 0: + pass + +if foo := 1: + pass + +if y := 5 + 5: + pass + +y = (x := 0) + +y += (x := 0) + +(y := 5 + 5) + +test: int = (test2 := 2) + +a, b = (test := (1, 2)) + +# see also https://github.com/psf/black/issues/2139 +assert (foo := 42 - 12) + +foo(x=(y := f(x))) + + +def foo(answer=(p := 42)): + ... + + +def foo2(answer: (p := 42) = 5): + ... + + +lambda: (x := 1) + +a[(x := 12)] +a[:(x := 13)] + +# we don't touch expressions in f-strings but if we do one day, don't break 'em +f"{(x:=10)}" + + +def a(): + return (x := 3) + await (b := 1) + yield (a := 2) + raise (c := 3) + + +def this_is_so_dumb() -> (please := no): + pass + + +async def await_the_walrus(): + with (x := y): + pass + + with (x := y) as z, (a := b) as c: + pass + + with (x := await y): + pass + + with (x := await a, y := await b): + pass + + with (x := await a, y := await b): + pass + + with (x := await a), (y := await b): + pass +``` + + diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_39__pep_572_py39.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_39__pep_572_py39.py.snap deleted file mode 100644 index 561947c70264e..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_39__pep_572_py39.py.snap +++ /dev/null @@ -1,54 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_39/pep_572_py39.py ---- -## Input - -```py -# Unparenthesized walruses are now allowed in set literals & set comprehensions -# since Python 3.9 -{x := 1, 2, 3} -{x4 := x**5 for x in range(7)} -# We better not remove the parentheses here (since it's a 3.10 feature) -x[(a := 1)] -x[(a := 1), (b := 3)] -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -4,4 +4,4 @@ - {x4 := x**5 for x in range(7)} - # We better not remove the parentheses here (since it's a 3.10 feature) - x[(a := 1)] --x[(a := 1), (b := 3)] -+x[((a := 1), (b := 3))] -``` - -## Ruff Output - -```py -# Unparenthesized walruses are now allowed in set literals & set comprehensions -# since Python 3.9 -{x := 1, 2, 3} -{x4 := x**5 for x in range(7)} -# We better not remove the parentheses here (since it's a 3.10 feature) -x[(a := 1)] -x[((a := 1), (b := 3))] -``` - -## Black Output - -```py -# Unparenthesized walruses are now allowed in set literals & set comprehensions -# since Python 3.9 -{x := 1, 2, 3} -{x4 := x**5 for x in range(7)} -# We better not remove the parentheses here (since it's a 3.10 feature) -x[(a := 1)] -x[(a := 1), (b := 3)] -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__class_methods_new_line.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__class_methods_new_line.py.snap deleted file mode 100644 index 436b6923ff372..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__class_methods_new_line.py.snap +++ /dev/null @@ -1,485 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/class_methods_new_line.py ---- -## Input - -```py -class ClassSimplest: - pass -class ClassWithSingleField: - a = 1 -class ClassWithJustTheDocstring: - """Just a docstring.""" -class ClassWithInit: - def __init__(self): - pass -class ClassWithTheDocstringAndInit: - """Just a docstring.""" - def __init__(self): - pass -class ClassWithInitAndVars: - cls_var = 100 - def __init__(self): - pass -class ClassWithInitAndVarsAndDocstring: - """Test class""" - cls_var = 100 - def __init__(self): - pass -class ClassWithDecoInit: - @deco - def __init__(self): - pass -class ClassWithDecoInitAndVars: - cls_var = 100 - @deco - def __init__(self): - pass -class ClassWithDecoInitAndVarsAndDocstring: - """Test class""" - cls_var = 100 - @deco - def __init__(self): - pass -class ClassSimplestWithInner: - class Inner: - pass -class ClassSimplestWithInnerWithDocstring: - class Inner: - """Just a docstring.""" - def __init__(self): - pass -class ClassWithSingleFieldWithInner: - a = 1 - class Inner: - pass -class ClassWithJustTheDocstringWithInner: - """Just a docstring.""" - class Inner: - pass -class ClassWithInitWithInner: - class Inner: - pass - def __init__(self): - pass -class ClassWithInitAndVarsWithInner: - cls_var = 100 - class Inner: - pass - def __init__(self): - pass -class ClassWithInitAndVarsAndDocstringWithInner: - """Test class""" - cls_var = 100 - class Inner: - pass - def __init__(self): - pass -class ClassWithDecoInitWithInner: - class Inner: - pass - @deco - def __init__(self): - pass -class ClassWithDecoInitAndVarsWithInner: - cls_var = 100 - class Inner: - pass - @deco - def __init__(self): - pass -class ClassWithDecoInitAndVarsAndDocstringWithInner: - """Test class""" - cls_var = 100 - class Inner: - pass - @deco - def __init__(self): - pass -class ClassWithDecoInitAndVarsAndDocstringWithInner2: - """Test class""" - class Inner: - pass - cls_var = 100 - @deco - def __init__(self): - pass -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -31,7 +31,6 @@ - - class ClassWithInitAndVarsAndDocstring: - """Test class""" -- - cls_var = 100 - - def __init__(self): -@@ -54,7 +53,6 @@ - - class ClassWithDecoInitAndVarsAndDocstring: - """Test class""" -- - cls_var = 100 - - @deco -@@ -109,7 +107,6 @@ - - class ClassWithInitAndVarsAndDocstringWithInner: - """Test class""" -- - cls_var = 100 - - class Inner: -@@ -141,7 +138,6 @@ - - class ClassWithDecoInitAndVarsAndDocstringWithInner: - """Test class""" -- - cls_var = 100 - - class Inner: -``` - -## Ruff Output - -```py -class ClassSimplest: - pass - - -class ClassWithSingleField: - a = 1 - - -class ClassWithJustTheDocstring: - """Just a docstring.""" - - -class ClassWithInit: - def __init__(self): - pass - - -class ClassWithTheDocstringAndInit: - """Just a docstring.""" - - def __init__(self): - pass - - -class ClassWithInitAndVars: - cls_var = 100 - - def __init__(self): - pass - - -class ClassWithInitAndVarsAndDocstring: - """Test class""" - cls_var = 100 - - def __init__(self): - pass - - -class ClassWithDecoInit: - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVars: - cls_var = 100 - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstring: - """Test class""" - cls_var = 100 - - @deco - def __init__(self): - pass - - -class ClassSimplestWithInner: - class Inner: - pass - - -class ClassSimplestWithInnerWithDocstring: - class Inner: - """Just a docstring.""" - - def __init__(self): - pass - - -class ClassWithSingleFieldWithInner: - a = 1 - - class Inner: - pass - - -class ClassWithJustTheDocstringWithInner: - """Just a docstring.""" - - class Inner: - pass - - -class ClassWithInitWithInner: - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithInitAndVarsWithInner: - cls_var = 100 - - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithInitAndVarsAndDocstringWithInner: - """Test class""" - cls_var = 100 - - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithDecoInitWithInner: - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsWithInner: - cls_var = 100 - - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstringWithInner: - """Test class""" - cls_var = 100 - - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstringWithInner2: - """Test class""" - - class Inner: - pass - - cls_var = 100 - - @deco - def __init__(self): - pass -``` - -## Black Output - -```py -class ClassSimplest: - pass - - -class ClassWithSingleField: - a = 1 - - -class ClassWithJustTheDocstring: - """Just a docstring.""" - - -class ClassWithInit: - def __init__(self): - pass - - -class ClassWithTheDocstringAndInit: - """Just a docstring.""" - - def __init__(self): - pass - - -class ClassWithInitAndVars: - cls_var = 100 - - def __init__(self): - pass - - -class ClassWithInitAndVarsAndDocstring: - """Test class""" - - cls_var = 100 - - def __init__(self): - pass - - -class ClassWithDecoInit: - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVars: - cls_var = 100 - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstring: - """Test class""" - - cls_var = 100 - - @deco - def __init__(self): - pass - - -class ClassSimplestWithInner: - class Inner: - pass - - -class ClassSimplestWithInnerWithDocstring: - class Inner: - """Just a docstring.""" - - def __init__(self): - pass - - -class ClassWithSingleFieldWithInner: - a = 1 - - class Inner: - pass - - -class ClassWithJustTheDocstringWithInner: - """Just a docstring.""" - - class Inner: - pass - - -class ClassWithInitWithInner: - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithInitAndVarsWithInner: - cls_var = 100 - - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithInitAndVarsAndDocstringWithInner: - """Test class""" - - cls_var = 100 - - class Inner: - pass - - def __init__(self): - pass - - -class ClassWithDecoInitWithInner: - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsWithInner: - cls_var = 100 - - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstringWithInner: - """Test class""" - - cls_var = 100 - - class Inner: - pass - - @deco - def __init__(self): - pass - - -class ClassWithDecoInitAndVarsAndDocstringWithInner2: - """Test class""" - - class Inner: - pass - - cls_var = 100 - - @deco - def __init__(self): - pass -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap index 9628978a2c681..0e98a11642d25 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap @@ -180,17 +180,6 @@ instruction()#comment with bad spacing ```diff --- Black +++ Ruff -@@ -1,8 +1,8 @@ - from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( -- MyLovelyCompanyTeamProjectComponent, # NOT DRY -+ MyLovelyCompanyTeamProjectComponent # NOT DRY - ) - from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( -- MyLovelyCompanyTeamProjectComponent as component, # DRY -+ MyLovelyCompanyTeamProjectComponent as component # DRY - ) - - # Please keep __all__ alphabetized within each category. @@ -60,8 +60,12 @@ # Comment before function. def inline_comments_in_brackets_ruin_everything(): @@ -259,10 +248,10 @@ instruction()#comment with bad spacing ```py from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent # NOT DRY + MyLovelyCompanyTeamProjectComponent, # NOT DRY ) from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent as component # DRY + MyLovelyCompanyTeamProjectComponent as component, # DRY ) # Please keep __all__ alphabetized within each category. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap deleted file mode 100644 index b7752423a8e47..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap +++ /dev/null @@ -1,348 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments4.py ---- -## Input - -```py -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent, # NOT DRY -) -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent as component, # DRY -) - - -class C: - @pytest.mark.parametrize( - ("post_data", "message"), - [ - # metadata_version errors. - ( - {}, - "None is an invalid value for Metadata-Version. Error: This field is" - " required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "-1"}, - "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata" - " Version see" - " https://packaging.python.org/specifications/core-metadata", - ), - # name errors. - ( - {"metadata_version": "1.2"}, - "'' is an invalid value for Name. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "foo-"}, - "'foo-' is an invalid value for Name. Error: Must start and end with a" - " letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - # version errors. - ( - {"metadata_version": "1.2", "name": "example"}, - "'' is an invalid value for Version. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "example", "version": "dog"}, - "'dog' is an invalid value for Version. Error: Must start and end with" - " a letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - ], - ) - def test_fails_invalid_post_data( - self, pyramid_config, db_request, post_data, message - ): - pyramid_config.testing_securitypolicy(userid=1) - db_request.POST = MultiDict(post_data) - - -def foo(list_a, list_b): - results = ( - User.query.filter(User.foo == "bar") - .filter( # Because foo. - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - # Another comment about the filtering on is_quux goes here. - .filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))) - .order_by(User.created_at.desc()) - .with_for_update(key_share=True) - .all() - ) - return results - - -def foo2(list_a, list_b): - # Standalone comment reasonably placed. - return ( - User.query.filter(User.foo == "bar") - .filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - ) - - -def foo3(list_a, list_b): - return ( - # Standalone comment but weirdly placed. - User.query.filter(User.foo == "bar") - .filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - ) -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -58,37 +58,28 @@ - - def foo(list_a, list_b): - results = ( -- User.query.filter(User.foo == "bar") -- .filter( # Because foo. -+ User.query.filter(User.foo == "bar").filter( # Because foo. - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) -- ) -- .filter(User.xyz.is_(None)) -+ ).filter(User.xyz.is_(None)). - # Another comment about the filtering on is_quux goes here. -- .filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))) -- .order_by(User.created_at.desc()) -- .with_for_update(key_share=True) -- .all() -+ filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))).order_by( -+ User.created_at.desc() -+ ).with_for_update(key_share=True).all() - ) - return results - - - def foo2(list_a, list_b): - # Standalone comment reasonably placed. -- return ( -- User.query.filter(User.foo == "bar") -- .filter( -- db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) -- ) -- .filter(User.xyz.is_(None)) -- ) -+ return User.query.filter(User.foo == "bar").filter( -+ db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) -+ ).filter(User.xyz.is_(None)) - - - def foo3(list_a, list_b): - return ( - # Standalone comment but weirdly placed. -- User.query.filter(User.foo == "bar") -- .filter( -+ User.query.filter(User.foo == "bar").filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) -- ) -- .filter(User.xyz.is_(None)) -+ ).filter(User.xyz.is_(None)) - ) -``` - -## Ruff Output - -```py -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent, # NOT DRY -) -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent as component, # DRY -) - - -class C: - @pytest.mark.parametrize( - ("post_data", "message"), - [ - # metadata_version errors. - ( - {}, - "None is an invalid value for Metadata-Version. Error: This field is" - " required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "-1"}, - "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata" - " Version see" - " https://packaging.python.org/specifications/core-metadata", - ), - # name errors. - ( - {"metadata_version": "1.2"}, - "'' is an invalid value for Name. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "foo-"}, - "'foo-' is an invalid value for Name. Error: Must start and end with a" - " letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - # version errors. - ( - {"metadata_version": "1.2", "name": "example"}, - "'' is an invalid value for Version. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "example", "version": "dog"}, - "'dog' is an invalid value for Version. Error: Must start and end with" - " a letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - ], - ) - def test_fails_invalid_post_data( - self, pyramid_config, db_request, post_data, message - ): - pyramid_config.testing_securitypolicy(userid=1) - db_request.POST = MultiDict(post_data) - - -def foo(list_a, list_b): - results = ( - User.query.filter(User.foo == "bar").filter( # Because foo. - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ).filter(User.xyz.is_(None)). - # Another comment about the filtering on is_quux goes here. - filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))).order_by( - User.created_at.desc() - ).with_for_update(key_share=True).all() - ) - return results - - -def foo2(list_a, list_b): - # Standalone comment reasonably placed. - return User.query.filter(User.foo == "bar").filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ).filter(User.xyz.is_(None)) - - -def foo3(list_a, list_b): - return ( - # Standalone comment but weirdly placed. - User.query.filter(User.foo == "bar").filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ).filter(User.xyz.is_(None)) - ) -``` - -## Black Output - -```py -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent, # NOT DRY -) -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent as component, # DRY -) - - -class C: - @pytest.mark.parametrize( - ("post_data", "message"), - [ - # metadata_version errors. - ( - {}, - "None is an invalid value for Metadata-Version. Error: This field is" - " required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "-1"}, - "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata" - " Version see" - " https://packaging.python.org/specifications/core-metadata", - ), - # name errors. - ( - {"metadata_version": "1.2"}, - "'' is an invalid value for Name. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "foo-"}, - "'foo-' is an invalid value for Name. Error: Must start and end with a" - " letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - # version errors. - ( - {"metadata_version": "1.2", "name": "example"}, - "'' is an invalid value for Version. Error: This field is required. see" - " https://packaging.python.org/specifications/core-metadata", - ), - ( - {"metadata_version": "1.2", "name": "example", "version": "dog"}, - "'dog' is an invalid value for Version. Error: Must start and end with" - " a letter or numeral and contain only ascii numeric and '.', '_' and" - " '-'. see https://packaging.python.org/specifications/core-metadata", - ), - ], - ) - def test_fails_invalid_post_data( - self, pyramid_config, db_request, post_data, message - ): - pyramid_config.testing_securitypolicy(userid=1) - db_request.POST = MultiDict(post_data) - - -def foo(list_a, list_b): - results = ( - User.query.filter(User.foo == "bar") - .filter( # Because foo. - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - # Another comment about the filtering on is_quux goes here. - .filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))) - .order_by(User.created_at.desc()) - .with_for_update(key_share=True) - .all() - ) - return results - - -def foo2(list_a, list_b): - # Standalone comment reasonably placed. - return ( - User.query.filter(User.foo == "bar") - .filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - ) - - -def foo3(list_a, list_b): - return ( - # Standalone comment but weirdly placed. - User.query.filter(User.foo == "bar") - .filter( - db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) - ) -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap index 6be2a77bc13c3..6725d8d840c1f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap @@ -141,7 +141,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite an_element_with_a_long_value = calls() or more_calls() and more() # type: bool tup = ( -@@ -100,19 +98,30 @@ +@@ -100,7 +98,13 @@ ) c = call( @@ -156,10 +156,9 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite ) --result = ( # aaa -- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --) -+result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa +@@ -108,11 +112,18 @@ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ) -AAAAAAAAAAAAA = [AAAAAAAAAAAAA] + SHARED_AAAAAAAAAAAAA + USER_AAAAAAAAAAAAA + AAAAAAAAAAAAA # type: ignore +AAAAAAAAAAAAA = ( @@ -293,7 +292,9 @@ def func( ) -result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa +result = ( # aaa + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +) AAAAAAAAAAAAA = ( [AAAAAAAAAAAAA] + SHARED_AAAAAAAAAAAAA + USER_AAAAAAAAAAAAA + AAAAAAAAAAAAA diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap deleted file mode 100644 index e8c73055d0c21..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap +++ /dev/null @@ -1,105 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments_non_breaking_space.py ---- -## Input - -```py -from .config import ( ConfigTypeAttributes, Int, Path, # String, - # DEFAULT_TYPE_ATTRIBUTES, -) - -result = 1 # A simple comment -result = ( 1, ) # Another one - -result = 1 # type: ignore -result = 1# This comment is talking about type: ignore -square = Square(4) # type: Optional[Square] - -def function(a:int=42): - """ This docstring is already formatted - a - b - """ - #  There's a NBSP + 3 spaces before - # And 4 spaces on the next line - pass -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -14,9 +14,9 @@ - - - def function(a: int = 42): -- """This docstring is already formatted -- a -- b -+ """ This docstring is already formatted -+ a -+ b - """ - # There's a NBSP + 3 spaces before - # And 4 spaces on the next line -``` - -## Ruff Output - -```py -from .config import ( - ConfigTypeAttributes, - Int, - Path, # String, - # DEFAULT_TYPE_ATTRIBUTES, -) - -result = 1 # A simple comment -result = (1,) # Another one - -result = 1 #  type: ignore -result = 1 # This comment is talking about type: ignore -square = Square(4) #  type: Optional[Square] - - -def function(a: int = 42): - """ This docstring is already formatted - a - b - """ - # There's a NBSP + 3 spaces before - # And 4 spaces on the next line - pass -``` - -## Black Output - -```py -from .config import ( - ConfigTypeAttributes, - Int, - Path, # String, - # DEFAULT_TYPE_ATTRIBUTES, -) - -result = 1 # A simple comment -result = (1,) # Another one - -result = 1 #  type: ignore -result = 1 # This comment is talking about type: ignore -square = Square(4) #  type: Optional[Square] - - -def function(a: int = 42): - """This docstring is already formatted - a - b - """ - # There's a NBSP + 3 spaces before - # And 4 spaces on the next line - pass -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition.py.snap index e012b766e5789..25780932c65c9 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition.py.snap @@ -193,16 +193,6 @@ class C: ```diff --- Black +++ Ruff -@@ -28,8 +28,8 @@ - while ( - # Just a comment - call() -+ ): - # Another -- ): - print(i) - xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( - push_manager=context.request.resource_manager, @@ -110,19 +110,20 @@ value, is_going_to_be="too long to fit in a single line", srsly=True ), "Not what we expected" @@ -293,8 +283,8 @@ class C: while ( # Just a comment call() - ): # Another + ): print(i) xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( push_manager=context.request.resource_manager, diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition_no_trailing_comma.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition_no_trailing_comma.py.snap index 8de3059b3bca3..48a59144c5692 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition_no_trailing_comma.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__composition_no_trailing_comma.py.snap @@ -193,16 +193,6 @@ class C: ```diff --- Black +++ Ruff -@@ -28,8 +28,8 @@ - while ( - # Just a comment - call() -+ ): - # Another -- ): - print(i) - xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( - push_manager=context.request.resource_manager, @@ -110,19 +110,20 @@ value, is_going_to_be="too long to fit in a single line", srsly=True ), "Not what we expected" @@ -293,8 +283,8 @@ class C: while ( # Just a comment call() - ): # Another + ): print(i) xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( push_manager=context.request.resource_manager, diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring.py.snap deleted file mode 100644 index 60a50df3a5713..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring.py.snap +++ /dev/null @@ -1,924 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/docstring.py ---- -## Input - -```py -class MyClass: - """ Multiline - class docstring - """ - - def method(self): - """Multiline - method docstring - """ - pass - - -def foo(): - """This is a docstring with - some lines of text here - """ - return - - -def bar(): - '''This is another docstring - with more lines of text - ''' - return - - -def baz(): - '''"This" is a string with some - embedded "quotes"''' - return - - -def troz(): - '''Indentation with tabs - is just as OK - ''' - return - - -def zort(): - """Another - multiline - docstring - """ - pass - -def poit(): - """ - Lorem ipsum dolor sit amet. - - Consectetur adipiscing elit: - - sed do eiusmod tempor incididunt ut labore - - dolore magna aliqua - - enim ad minim veniam - - quis nostrud exercitation ullamco laboris nisi - - aliquip ex ea commodo consequat - """ - pass - - -def under_indent(): - """ - These lines are indented in a way that does not -make sense. - """ - pass - - -def over_indent(): - """ - This has a shallow indent - - But some lines are deeper - - And the closing quote is too deep - """ - pass - - -def single_line(): - """But with a newline after it! - - """ - pass - - -def this(): - r""" - 'hey ho' - """ - - -def that(): - """ "hey yah" """ - - -def and_that(): - """ - "hey yah" """ - - -def and_this(): - ''' - "hey yah"''' - - -def multiline_whitespace(): - ''' - - - - - ''' - - -def oneline_whitespace(): - ''' ''' - - -def empty(): - """""" - - -def single_quotes(): - 'testing' - - -def believe_it_or_not_this_is_in_the_py_stdlib(): ''' -"hey yah"''' - - -def ignored_docstring(): - """a => \ -b""" - -def single_line_docstring_with_whitespace(): - """ This should be stripped """ - -def docstring_with_inline_tabs_and_space_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - - -def docstring_with_inline_tabs_and_tab_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - pass - - -def backslash_space(): - """\ """ - - -def multiline_backslash_1(): - ''' - hey\there\ - \ ''' - - -def multiline_backslash_2(): - ''' - hey there \ ''' - -# Regression test for #3425 -def multiline_backslash_really_long_dont_crash(): - """ - hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """ - - -def multiline_backslash_3(): - ''' - already escaped \\ ''' - - -def my_god_its_full_of_stars_1(): - "I'm sorry Dave\u2001" - - -# the space below is actually a \u2001, removed in output -def my_god_its_full_of_stars_2(): - "I'm sorry Dave " - - -def docstring_almost_at_line_limit(): - """long docstring.................................................................""" - - -def docstring_almost_at_line_limit2(): - """long docstring................................................................. - - .................................................................................. - """ - - -def docstring_at_line_limit(): - """long docstring................................................................""" - - -def multiline_docstring_at_line_limit(): - """first line----------------------------------------------------------------------- - - second line----------------------------------------------------------------------""" - - -def stable_quote_normalization_with_immediate_inner_single_quote(self): - '''' - - - ''' -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,83 +1,85 @@ - class MyClass: -- """Multiline -- class docstring -- """ -+ """ Multiline -+ class docstring -+ """ - - def method(self): - """Multiline -- method docstring -- """ -+ method docstring -+ """ - pass - - - def foo(): -- """This is a docstring with -- some lines of text here -- """ -+ """This is a docstring with -+ some lines of text here -+ """ - return - - - def bar(): - """This is another docstring -- with more lines of text -- """ -+ with more lines of text -+ """ - return - - - def baz(): - '''"This" is a string with some -- embedded "quotes"''' -+ embedded "quotes"''' - return - - - def troz(): - """Indentation with tabs -- is just as OK -- """ -+ is just as OK -+ """ - return - - - def zort(): - """Another -- multiline -- docstring -- """ -+ multiline -+ docstring -+ """ - pass - - - def poit(): - """ -- Lorem ipsum dolor sit amet. -+ Lorem ipsum dolor sit amet. - -- Consectetur adipiscing elit: -- - sed do eiusmod tempor incididunt ut labore -- - dolore magna aliqua -- - enim ad minim veniam -- - quis nostrud exercitation ullamco laboris nisi -- - aliquip ex ea commodo consequat -- """ -+ Consectetur adipiscing elit: -+ - sed do eiusmod tempor incididunt ut labore -+ - dolore magna aliqua -+ - enim ad minim veniam -+ - quis nostrud exercitation ullamco laboris nisi -+ - aliquip ex ea commodo consequat -+ """ - pass - - - def under_indent(): - """ -- These lines are indented in a way that does not -- make sense. -- """ -+ These lines are indented in a way that does not -+make sense. -+ """ - pass - - - def over_indent(): - """ -- This has a shallow indent -- - But some lines are deeper -- - And the closing quote is too deep -+ This has a shallow indent -+ - But some lines are deeper -+ - And the closing quote is too deep - """ - pass - - - def single_line(): -- """But with a newline after it!""" -+ """But with a newline after it! -+ -+ """ - pass - - -@@ -93,20 +95,25 @@ - - def and_that(): - """ -- "hey yah" """ -+ "hey yah" """ - - - def and_this(): -- ''' -- "hey yah"''' -+ ''' -+ "hey yah"''' - - - def multiline_whitespace(): -- """ """ -+ """ -+ -+ -+ -+ -+ """ - - - def oneline_whitespace(): -- """ """ -+ """ """ - - - def empty(): -@@ -118,8 +125,8 @@ - - - def believe_it_or_not_this_is_in_the_py_stdlib(): -- ''' -- "hey yah"''' -+ ''' -+"hey yah"''' - - - def ignored_docstring(): -@@ -128,31 +135,31 @@ - - - def single_line_docstring_with_whitespace(): -- """This should be stripped""" -+ """ This should be stripped """ - - - def docstring_with_inline_tabs_and_space_indentation(): - """hey - - tab separated value -- tab at start of line and then a tab separated value -- multiple tabs at the beginning and inline -- mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. -- -- line ends with some tabs -+ tab at start of line and then a tab separated value -+ multiple tabs at the beginning and inline -+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. -+ -+ line ends with some tabs - """ - - - def docstring_with_inline_tabs_and_tab_indentation(): - """hey - -- tab separated value -- tab at start of line and then a tab separated value -- multiple tabs at the beginning and inline -- mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. -- -- line ends with some tabs -- """ -+ tab separated value -+ tab at start of line and then a tab separated value -+ multiple tabs at the beginning and inline -+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. -+ -+ line ends with some tabs -+ """ - pass - - -@@ -168,7 +175,7 @@ - - def multiline_backslash_2(): - """ -- hey there \ """ -+ hey there \ """ - - - # Regression test for #3425 -@@ -179,7 +186,7 @@ - - def multiline_backslash_3(): - """ -- already escaped \\""" -+ already escaped \\ """ - - - def my_god_its_full_of_stars_1(): -@@ -188,7 +195,7 @@ - - # the space below is actually a \u2001, removed in output - def my_god_its_full_of_stars_2(): -- "I'm sorry Dave" -+ "I'm sorry Dave " - - - def docstring_almost_at_line_limit(): -``` - -## Ruff Output - -```py -class MyClass: - """ Multiline - class docstring - """ - - def method(self): - """Multiline - method docstring - """ - pass - - -def foo(): - """This is a docstring with - some lines of text here - """ - return - - -def bar(): - """This is another docstring - with more lines of text - """ - return - - -def baz(): - '''"This" is a string with some - embedded "quotes"''' - return - - -def troz(): - """Indentation with tabs - is just as OK - """ - return - - -def zort(): - """Another - multiline - docstring - """ - pass - - -def poit(): - """ - Lorem ipsum dolor sit amet. - - Consectetur adipiscing elit: - - sed do eiusmod tempor incididunt ut labore - - dolore magna aliqua - - enim ad minim veniam - - quis nostrud exercitation ullamco laboris nisi - - aliquip ex ea commodo consequat - """ - pass - - -def under_indent(): - """ - These lines are indented in a way that does not -make sense. - """ - pass - - -def over_indent(): - """ - This has a shallow indent - - But some lines are deeper - - And the closing quote is too deep - """ - pass - - -def single_line(): - """But with a newline after it! - - """ - pass - - -def this(): - r""" - 'hey ho' - """ - - -def that(): - """ "hey yah" """ - - -def and_that(): - """ - "hey yah" """ - - -def and_this(): - ''' - "hey yah"''' - - -def multiline_whitespace(): - """ - - - - - """ - - -def oneline_whitespace(): - """ """ - - -def empty(): - """""" - - -def single_quotes(): - "testing" - - -def believe_it_or_not_this_is_in_the_py_stdlib(): - ''' -"hey yah"''' - - -def ignored_docstring(): - """a => \ -b""" - - -def single_line_docstring_with_whitespace(): - """ This should be stripped """ - - -def docstring_with_inline_tabs_and_space_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - - -def docstring_with_inline_tabs_and_tab_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - pass - - -def backslash_space(): - """\ """ - - -def multiline_backslash_1(): - """ - hey\there\ - \ """ - - -def multiline_backslash_2(): - """ - hey there \ """ - - -# Regression test for #3425 -def multiline_backslash_really_long_dont_crash(): - """ - hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """ - - -def multiline_backslash_3(): - """ - already escaped \\ """ - - -def my_god_its_full_of_stars_1(): - "I'm sorry Dave\u2001" - - -# the space below is actually a \u2001, removed in output -def my_god_its_full_of_stars_2(): - "I'm sorry Dave " - - -def docstring_almost_at_line_limit(): - """long docstring.................................................................""" - - -def docstring_almost_at_line_limit2(): - """long docstring................................................................. - - .................................................................................. - """ - - -def docstring_at_line_limit(): - """long docstring................................................................""" - - -def multiline_docstring_at_line_limit(): - """first line----------------------------------------------------------------------- - - second line----------------------------------------------------------------------""" - - -def stable_quote_normalization_with_immediate_inner_single_quote(self): - """' - - - """ -``` - -## Black Output - -```py -class MyClass: - """Multiline - class docstring - """ - - def method(self): - """Multiline - method docstring - """ - pass - - -def foo(): - """This is a docstring with - some lines of text here - """ - return - - -def bar(): - """This is another docstring - with more lines of text - """ - return - - -def baz(): - '''"This" is a string with some - embedded "quotes"''' - return - - -def troz(): - """Indentation with tabs - is just as OK - """ - return - - -def zort(): - """Another - multiline - docstring - """ - pass - - -def poit(): - """ - Lorem ipsum dolor sit amet. - - Consectetur adipiscing elit: - - sed do eiusmod tempor incididunt ut labore - - dolore magna aliqua - - enim ad minim veniam - - quis nostrud exercitation ullamco laboris nisi - - aliquip ex ea commodo consequat - """ - pass - - -def under_indent(): - """ - These lines are indented in a way that does not - make sense. - """ - pass - - -def over_indent(): - """ - This has a shallow indent - - But some lines are deeper - - And the closing quote is too deep - """ - pass - - -def single_line(): - """But with a newline after it!""" - pass - - -def this(): - r""" - 'hey ho' - """ - - -def that(): - """ "hey yah" """ - - -def and_that(): - """ - "hey yah" """ - - -def and_this(): - ''' - "hey yah"''' - - -def multiline_whitespace(): - """ """ - - -def oneline_whitespace(): - """ """ - - -def empty(): - """""" - - -def single_quotes(): - "testing" - - -def believe_it_or_not_this_is_in_the_py_stdlib(): - ''' - "hey yah"''' - - -def ignored_docstring(): - """a => \ -b""" - - -def single_line_docstring_with_whitespace(): - """This should be stripped""" - - -def docstring_with_inline_tabs_and_space_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - - -def docstring_with_inline_tabs_and_tab_indentation(): - """hey - - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. - - line ends with some tabs - """ - pass - - -def backslash_space(): - """\ """ - - -def multiline_backslash_1(): - """ - hey\there\ - \ """ - - -def multiline_backslash_2(): - """ - hey there \ """ - - -# Regression test for #3425 -def multiline_backslash_really_long_dont_crash(): - """ - hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """ - - -def multiline_backslash_3(): - """ - already escaped \\""" - - -def my_god_its_full_of_stars_1(): - "I'm sorry Dave\u2001" - - -# the space below is actually a \u2001, removed in output -def my_god_its_full_of_stars_2(): - "I'm sorry Dave" - - -def docstring_almost_at_line_limit(): - """long docstring.................................................................""" - - -def docstring_almost_at_line_limit2(): - """long docstring................................................................. - - .................................................................................. - """ - - -def docstring_at_line_limit(): - """long docstring................................................................""" - - -def multiline_docstring_at_line_limit(): - """first line----------------------------------------------------------------------- - - second line----------------------------------------------------------------------""" - - -def stable_quote_normalization_with_immediate_inner_single_quote(self): - """' - - - """ -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring_preview.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring_preview.py.snap index 427408a63cc7d..dad30c4cb8fef 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring_preview.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__docstring_preview.py.snap @@ -62,11 +62,7 @@ def single_quote_docstring_over_line_limit2(): ```diff --- Black +++ Ruff -@@ -1,9 +1,11 @@ - def docstring_almost_at_line_limit(): -- """long docstring.................................................................""" -+ """long docstring................................................................. -+ """ +@@ -3,7 +3,8 @@ def docstring_almost_at_line_limit_with_prefix(): @@ -82,8 +78,7 @@ def single_quote_docstring_over_line_limit2(): ```py def docstring_almost_at_line_limit(): - """long docstring................................................................. - """ + """long docstring.................................................................""" def docstring_almost_at_line_limit_with_prefix(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__expression.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__expression.py.snap index ad9938cb83183..86a5b37df9883 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__expression.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__expression.py.snap @@ -300,40 +300,7 @@ last_call() ) # note: no trailing comma pre-3.6 call(*gidgets[:2]) call(a, *gidgets[:2]) -@@ -208,24 +209,14 @@ - what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( - vars_to_remove - ) --result = ( -- session.query(models.Customer.id) -- .filter( -- models.Customer.account_id == account_id, models.Customer.email == email_address -- ) -- .order_by(models.Customer.id.asc()) -- .all() --) --result = ( -- session.query(models.Customer.id) -- .filter( -- models.Customer.account_id == account_id, models.Customer.email == email_address -- ) -- .order_by( -- models.Customer.id.asc(), -- ) -- .all() --) -+result = session.query(models.Customer.id).filter( -+ models.Customer.account_id == account_id, models.Customer.email == email_address -+).order_by(models.Customer.id.asc()).all() -+result = session.query(models.Customer.id).filter( -+ models.Customer.account_id == account_id, models.Customer.email == email_address -+).order_by( -+ models.Customer.id.asc(), -+).all() - Ø = set() - authors.łukasz.say_thanks() - mapping = { -@@ -328,13 +319,18 @@ +@@ -328,13 +329,18 @@ ): return True if ( @@ -355,7 +322,7 @@ last_call() ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True -@@ -342,7 +338,8 @@ +@@ -342,7 +348,8 @@ ~aaaaaaaaaaaaaaaa.a + aaaaaaaaaaaaaaaa.b - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e @@ -581,14 +548,24 @@ what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + se what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( vars_to_remove ) -result = session.query(models.Customer.id).filter( - models.Customer.account_id == account_id, models.Customer.email == email_address -).order_by(models.Customer.id.asc()).all() -result = session.query(models.Customer.id).filter( - models.Customer.account_id == account_id, models.Customer.email == email_address -).order_by( - models.Customer.id.asc(), -).all() +result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ) + .order_by(models.Customer.id.asc()) + .all() +) +result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ) + .order_by( + models.Customer.id.asc(), + ) + .all() +) Ø = set() authors.łukasz.say_thanks() mapping = { diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap index 88e2db7a36ea8..91f218dcb2a65 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap @@ -198,77 +198,7 @@ d={'a':1, ```diff --- Black +++ Ruff -@@ -6,8 +6,8 @@ - - from library import some_connection, some_decorator - # fmt: off --from third_party import (X, -- Y, Z) -+from third_party import X, Y, Z -+ - # fmt: on - f"trigger 3.6 mode" - # Comment 1 -@@ -17,26 +17,40 @@ - - # fmt: off - def func_no_args(): -- a; b; c -- if True: raise RuntimeError -- if False: ... -- for i in range(10): -- print(i) -- continue -- exec('new-style exec', {}, {}) -- return None -+ a -+ b -+ c -+ if True: -+ raise RuntimeError -+ if False: -+ ... -+ for i in range(10): -+ print(i) -+ continue -+ exec("new-style exec", {}, {}) -+ return None -+ -+ - async def coroutine(arg, exec=False): -- 'Single-line docstring. Multiline is harder to reformat.' -- async with some_connection() as conn: -- await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2) -- await asyncio.sleep(1) -+ "Single-line docstring. Multiline is harder to reformat." -+ async with some_connection() as conn: -+ await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2) -+ await asyncio.sleep(1) -+ -+ - @asyncio.coroutine --@some_decorator( --with_args=True, --many_args=[1,2,3] --) --def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str: -- return text[number:-1] -+@some_decorator(with_args=True, many_args=[1, 2, 3]) -+def function_signature_stress_test( -+ number: int, -+ no_annotation=None, -+ text: str = "default", -+ *, -+ debug: bool = False, -+ **kwargs, -+) -> str: -+ return text[number:-1] -+ -+ - # fmt: on - def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""): - offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2))) -@@ -63,15 +77,15 @@ +@@ -63,15 +63,15 @@ something = { # fmt: off @@ -287,83 +217,28 @@ d={'a':1, # fmt: on goes + here, andhere, -@@ -80,38 +94,36 @@ - - def import_as_names(): +@@ -122,8 +122,10 @@ + """ # fmt: off -- from hello import a, b -- 'unformatted' -+ from hello import a, b -+ -+ "unformatted" - # fmt: on +- # hey, that won't work - def testlist_star_expr(): - # fmt: off -- a , b = *hello -- 'unformatted' -+ a, b = *hello -+ "unformatted" ++ #hey, that won't work ++ ++ # fmt: on + pass - - def yield_expr(): - # fmt: off - yield hello -- 'unformatted' -+ "unformatted" - # fmt: on - "formatted" - # fmt: off -- ( yield hello ) -- 'unformatted' -+ (yield hello) -+ "unformatted" +@@ -138,7 +140,7 @@ + now . considers . multiple . fmt . directives . within . one . prefix # fmt: on - - - def example(session): # fmt: off -- result = session\ -- .query(models.Customer.id)\ -- .filter(models.Customer.account_id == account_id, -- models.Customer.email == email_address)\ -- .order_by(models.Customer.id.asc())\ -- .all() -+ result = session.query(models.Customer.id).filter( -+ models.Customer.account_id == account_id, models.Customer.email == email_address -+ ).order_by(models.Customer.id.asc()).all() +- # ...but comments still get reformatted even though they should not be ++ # ...but comments still get reformatted even though they should not be # fmt: on -@@ -132,10 +144,10 @@ - """Another known limitation.""" - # fmt: on - # fmt: off -- this=should.not_be.formatted() -- and_=indeed . it is not formatted -- because . the . handling . inside . generate_ignored_nodes() -- now . considers . multiple . fmt . directives . within . one . prefix -+ this = should.not_be.formatted() -+ and_ = indeed.it is not formatted -+ because.the.handling.inside.generate_ignored_nodes() -+ now.considers.multiple.fmt.directives.within.one.prefix - # fmt: on - # fmt: off - # ...but comments still get reformatted even though they should not be -@@ -153,9 +165,7 @@ - ) - ) - # fmt: off -- a = ( -- unnecessary_bracket() -- ) -+ a = unnecessary_bracket() - # fmt: on - _type_comment_re = re.compile( - r""" -@@ -178,7 +188,7 @@ +@@ -178,14 +180,18 @@ $ """, # fmt: off @@ -372,18 +247,18 @@ d={'a':1, # fmt: on ) -@@ -216,8 +226,7 @@ - xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5, - ) - # fmt: off --yield 'hello' -+yield "hello" - # No formatting to the end of the file --l=[1,2,3] --d={'a':1, -- 'b':2} -+l = [1, 2, 3] -+d = {"a": 1, "b": 2} + + def single_literal_yapf_disable(): + """Black does not support this.""" +- BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable ++ BAZ = { ++ (1, 2, 3, 4), ++ (5, 6, 7, 8), ++ (9, 10, 11, 12) ++ } # yapf: disable + + + cfg.rule( ``` ## Ruff Output @@ -397,8 +272,8 @@ from third_party import X, Y, Z from library import some_connection, some_decorator # fmt: off -from third_party import X, Y, Z - +from third_party import (X, + Y, Z) # fmt: on f"trigger 3.6 mode" # Comment 1 @@ -408,40 +283,26 @@ f"trigger 3.6 mode" # fmt: off def func_no_args(): - a - b - c - if True: - raise RuntimeError - if False: - ... - for i in range(10): - print(i) - continue - exec("new-style exec", {}, {}) - return None - - + a; b; c + if True: raise RuntimeError + if False: ... + for i in range(10): + print(i) + continue + exec('new-style exec', {}, {}) + return None async def coroutine(arg, exec=False): - "Single-line docstring. Multiline is harder to reformat." - async with some_connection() as conn: - await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2) - await asyncio.sleep(1) - - + 'Single-line docstring. Multiline is harder to reformat.' + async with some_connection() as conn: + await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2) + await asyncio.sleep(1) @asyncio.coroutine -@some_decorator(with_args=True, many_args=[1, 2, 3]) -def function_signature_stress_test( - number: int, - no_annotation=None, - text: str = "default", - *, - debug: bool = False, - **kwargs, -) -> str: - return text[number:-1] - - +@some_decorator( +with_args=True, +many_args=[1,2,3] +) +def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str: + return text[number:-1] # fmt: on def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""): offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2))) @@ -485,36 +346,38 @@ def subscriptlist(): def import_as_names(): # fmt: off - from hello import a, b - - "unformatted" + from hello import a, b + 'unformatted' # fmt: on def testlist_star_expr(): # fmt: off - a, b = *hello - "unformatted" + a , b = *hello + 'unformatted' # fmt: on def yield_expr(): # fmt: off yield hello - "unformatted" + 'unformatted' # fmt: on "formatted" # fmt: off - (yield hello) - "unformatted" + ( yield hello ) + 'unformatted' # fmt: on def example(session): # fmt: off - result = session.query(models.Customer.id).filter( - models.Customer.account_id == account_id, models.Customer.email == email_address - ).order_by(models.Customer.id.asc()).all() + result = session\ + .query(models.Customer.id)\ + .filter(models.Customer.account_id == account_id, + models.Customer.email == email_address)\ + .order_by(models.Customer.id.asc())\ + .all() # fmt: on @@ -525,7 +388,9 @@ def off_and_on_without_data(): """ # fmt: off - # hey, that won't work + + #hey, that won't work + # fmt: on pass @@ -535,13 +400,13 @@ def on_and_off_broken(): """Another known limitation.""" # fmt: on # fmt: off - this = should.not_be.formatted() - and_ = indeed.it is not formatted - because.the.handling.inside.generate_ignored_nodes() - now.considers.multiple.fmt.directives.within.one.prefix + this=should.not_be.formatted() + and_=indeed . it is not formatted + because . the . handling . inside . generate_ignored_nodes() + now . considers . multiple . fmt . directives . within . one . prefix # fmt: on # fmt: off - # ...but comments still get reformatted even though they should not be + # ...but comments still get reformatted even though they should not be # fmt: on @@ -556,7 +421,9 @@ def long_lines(): ) ) # fmt: off - a = unnecessary_bracket() + a = ( + unnecessary_bracket() + ) # fmt: on _type_comment_re = re.compile( r""" @@ -586,7 +453,11 @@ def long_lines(): def single_literal_yapf_disable(): """Black does not support this.""" - BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable + BAZ = { + (1, 2, 3, 4), + (5, 6, 7, 8), + (9, 10, 11, 12) + } # yapf: disable cfg.rule( @@ -617,10 +488,11 @@ cfg.rule( xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5, ) # fmt: off -yield "hello" +yield 'hello' # No formatting to the end of the file -l = [1, 2, 3] -d = {"a": 1, "b": 2} +l=[1,2,3] +d={'a':1, + 'b':2} ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap deleted file mode 100644 index 012dd71335b64..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap +++ /dev/null @@ -1,201 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff2.py ---- -## Input - -```py -import pytest - -TmSt = 1 -TmEx = 2 - -# fmt: off - -# Test data: -# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] - -@pytest.mark.parametrize('test', [ - - # Test don't manage the volume - [ - ('stuff', 'in') - ], -]) -def test_fader(test): - pass - -def check_fader(test): - - pass - -def verify_fader(test): - # misaligned comment - pass - -def verify_fader(test): - """Hey, ho.""" - assert test.passed() - -def test_calculate_fades(): - calcs = [ - # one is zero/none - (0, 4, 0, 0, 10, 0, 0, 6, 10), - (None, 4, 0, 0, 10, 0, 0, 6, 10), - ] - -# fmt: on -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -5,36 +5,40 @@ - - # fmt: off - -+ - # Test data: - # Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] - --@pytest.mark.parametrize('test', [ -- -- # Test don't manage the volume -+@pytest.mark.parametrize( -+ "test", - [ -- ('stuff', 'in') -+ # Test don't manage the volume -+ [("stuff", "in")], - ], --]) -+) - def test_fader(test): - pass - -+ - def check_fader(test): -- - pass - -+ - def verify_fader(test): -- # misaligned comment -+ # misaligned comment - pass - -+ - def verify_fader(test): - """Hey, ho.""" - assert test.passed() - -+ - def test_calculate_fades(): - calcs = [ - # one is zero/none -- (0, 4, 0, 0, 10, 0, 0, 6, 10), -- (None, 4, 0, 0, 10, 0, 0, 6, 10), -+ (0, 4, 0, 0, 10, 0, 0, 6, 10), -+ (None, 4, 0, 0, 10, 0, 0, 6, 10), - ] - - # fmt: on -``` - -## Ruff Output - -```py -import pytest - -TmSt = 1 -TmEx = 2 - -# fmt: off - - -# Test data: -# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] - -@pytest.mark.parametrize( - "test", - [ - # Test don't manage the volume - [("stuff", "in")], - ], -) -def test_fader(test): - pass - - -def check_fader(test): - pass - - -def verify_fader(test): - # misaligned comment - pass - - -def verify_fader(test): - """Hey, ho.""" - assert test.passed() - - -def test_calculate_fades(): - calcs = [ - # one is zero/none - (0, 4, 0, 0, 10, 0, 0, 6, 10), - (None, 4, 0, 0, 10, 0, 0, 6, 10), - ] - -# fmt: on -``` - -## Black Output - -```py -import pytest - -TmSt = 1 -TmEx = 2 - -# fmt: off - -# Test data: -# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] - -@pytest.mark.parametrize('test', [ - - # Test don't manage the volume - [ - ('stuff', 'in') - ], -]) -def test_fader(test): - pass - -def check_fader(test): - - pass - -def verify_fader(test): - # misaligned comment - pass - -def verify_fader(test): - """Hey, ho.""" - assert test.passed() - -def test_calculate_fades(): - calcs = [ - # one is zero/none - (0, 4, 0, 0, 10, 0, 0, 6, 10), - (None, 4, 0, 0, 10, 0, 0, 6, 10), - ] - -# fmt: on -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff3.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff3.py.snap deleted file mode 100644 index 42ebc85486bba..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff3.py.snap +++ /dev/null @@ -1,101 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff3.py ---- -## Input - -```py -# fmt: off -x = [ - 1, 2, - 3, 4, -] -# fmt: on - -# fmt: off -x = [ - 1, 2, - 3, 4, -] -# fmt: on - -x = [ - 1, 2, 3, 4 -] -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,14 +1,18 @@ - # fmt: off - x = [ -- 1, 2, -- 3, 4, -+ 1, -+ 2, -+ 3, -+ 4, - ] - # fmt: on - - # fmt: off - x = [ -- 1, 2, -- 3, 4, -+ 1, -+ 2, -+ 3, -+ 4, - ] - # fmt: on - -``` - -## Ruff Output - -```py -# fmt: off -x = [ - 1, - 2, - 3, - 4, -] -# fmt: on - -# fmt: off -x = [ - 1, - 2, - 3, - 4, -] -# fmt: on - -x = [1, 2, 3, 4] -``` - -## Black Output - -```py -# fmt: off -x = [ - 1, 2, - 3, 4, -] -# fmt: on - -# fmt: off -x = [ - 1, 2, - 3, 4, -] -# fmt: on - -x = [1, 2, 3, 4] -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff4.py.snap index a8dc2ef62014f..5962f31f5f7b4 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff4.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff4.py.snap @@ -25,52 +25,48 @@ def f(): pass ```diff --- Black +++ Ruff -@@ -1,8 +1,12 @@ - # fmt: off --@test([ -- 1, 2, -- 3, 4, --]) -+@test( -+ [ -+ 1, -+ 2, -+ 3, -+ 4, -+ ] -+) +@@ -4,17 +4,10 @@ + 3, 4, + ]) # fmt: on - def f(): - pass +-def f(): +- pass +- ++def f(): pass + +-@test( +- [ +- 1, +- 2, +- 3, +- 4, +- ] +-) +-def f(): +- pass ++@test([ ++ 1, 2, ++ 3, 4, ++]) ++def f(): pass ``` ## Ruff Output ```py # fmt: off -@test( - [ - 1, - 2, - 3, - 4, - ] -) +@test([ + 1, 2, + 3, 4, +]) # fmt: on -def f(): - pass - +def f(): pass -@test( - [ - 1, - 2, - 3, - 4, - ] -) -def f(): - pass +@test([ + 1, 2, + 3, 4, +]) +def f(): pass ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff5.py.snap index 99e98844ffad4..b28415f3acc73 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff5.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff5.py.snap @@ -110,57 +110,7 @@ elif unformatted: }, ) -@@ -27,7 +26,7 @@ - # Regression test for https://github.com/psf/black/issues/3026. - def test_func(): - # yapf: disable -- if unformatted( args ): -+ if unformatted(args): - return True - # yapf: enable - elif b: -@@ -39,10 +38,10 @@ - # Regression test for https://github.com/psf/black/issues/2567. - if True: - # fmt: off -- for _ in range( 1 ): -- # fmt: on -- print ( "This won't be formatted" ) -- print ( "This won't be formatted either" ) -+ for _ in range(1): -+ # fmt: on -+ print("This won't be formatted") -+ print("This won't be formatted either") - else: - print("This will be formatted") - -@@ -52,14 +51,12 @@ - async def call(param): - if param: - # fmt: off -- if param[0:4] in ( -- "ABCD", "EFGH" -- ) : -+ if param[0:4] in ("ABCD", "EFGH"): - # fmt: on -- print ( "This won't be formatted" ) -+ print("This won't be formatted") - - elif param[0:4] in ("ZZZZ",): -- print ( "This won't be formatted either" ) -+ print("This won't be formatted either") - - print("This will be formatted") - -@@ -68,13 +65,13 @@ - class Named(t.Protocol): - # fmt: off - @property -- def this_wont_be_formatted ( self ) -> str: ... -+ def this_wont_be_formatted(self) -> str: -+ ... - - +@@ -74,7 +73,6 @@ class Factory(t.Protocol): def this_will_be_formatted(self, **kwargs) -> Named: ... @@ -168,7 +118,7 @@ elif unformatted: # fmt: on -@@ -82,6 +79,6 @@ +@@ -82,6 +80,6 @@ if x: return x # fmt: off @@ -209,7 +159,7 @@ run( # Regression test for https://github.com/psf/black/issues/3026. def test_func(): # yapf: disable - if unformatted(args): + if unformatted( args ): return True # yapf: enable elif b: @@ -221,10 +171,10 @@ def test_func(): # Regression test for https://github.com/psf/black/issues/2567. if True: # fmt: off - for _ in range(1): - # fmt: on - print("This won't be formatted") - print("This won't be formatted either") + for _ in range( 1 ): + # fmt: on + print ( "This won't be formatted" ) + print ( "This won't be formatted either" ) else: print("This will be formatted") @@ -234,12 +184,14 @@ class A: async def call(param): if param: # fmt: off - if param[0:4] in ("ABCD", "EFGH"): + if param[0:4] in ( + "ABCD", "EFGH" + ) : # fmt: on - print("This won't be formatted") + print ( "This won't be formatted" ) elif param[0:4] in ("ZZZZ",): - print("This won't be formatted either") + print ( "This won't be formatted either" ) print("This will be formatted") @@ -248,8 +200,7 @@ class A: class Named(t.Protocol): # fmt: off @property - def this_wont_be_formatted(self) -> str: - ... + def this_wont_be_formatted ( self ) -> str: ... class Factory(t.Protocol): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip.py.snap deleted file mode 100644 index 3c9f58710b10f..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip.py.snap +++ /dev/null @@ -1,41 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip.py ---- -## Input - -```py -a, b = 1, 2 -c = 6 # fmt: skip -d = 5 -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,3 +1,3 @@ - a, b = 1, 2 --c = 6 # fmt: skip -+c = 6 # fmt: skip - d = 5 -``` - -## Ruff Output - -```py -a, b = 1, 2 -c = 6 # fmt: skip -d = 5 -``` - -## Black Output - -```py -a, b = 1, 2 -c = 6 # fmt: skip -d = 5 -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip2.py.snap deleted file mode 100644 index 6b686d5412daf..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip2.py.snap +++ /dev/null @@ -1,69 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip2.py ---- -## Input - -```py -l1 = ["This list should be broken up", "into multiple lines", "because it is way too long"] -l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip -l3 = ["I have", "trailing comma", "so I should be braked",] -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -3,7 +3,11 @@ - "into multiple lines", - "because it is way too long", - ] --l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip -+l2 = [ -+ "But this list shouldn't", -+ "even though it also has", -+ "way too many characters in it", -+] # fmt: skip - l3 = [ - "I have", - "trailing comma", -``` - -## Ruff Output - -```py -l1 = [ - "This list should be broken up", - "into multiple lines", - "because it is way too long", -] -l2 = [ - "But this list shouldn't", - "even though it also has", - "way too many characters in it", -] # fmt: skip -l3 = [ - "I have", - "trailing comma", - "so I should be braked", -] -``` - -## Black Output - -```py -l1 = [ - "This list should be broken up", - "into multiple lines", - "because it is way too long", -] -l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip -l3 = [ - "I have", - "trailing comma", - "so I should be braked", -] -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip3.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip3.py.snap deleted file mode 100644 index 002454e8dafa9..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip3.py.snap +++ /dev/null @@ -1,64 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip3.py ---- -## Input - -```py -a = 3 -# fmt: off -b, c = 1, 2 -d = 6 # fmt: skip -e = 5 -# fmt: on -f = ["This is a very long line that should be formatted into a clearer line ", "by rearranging."] -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,7 +1,7 @@ - a = 3 - # fmt: off --b, c = 1, 2 --d = 6 # fmt: skip -+b, c = 1, 2 -+d = 6 # fmt: skip - e = 5 - # fmt: on - f = [ -``` - -## Ruff Output - -```py -a = 3 -# fmt: off -b, c = 1, 2 -d = 6 # fmt: skip -e = 5 -# fmt: on -f = [ - "This is a very long line that should be formatted into a clearer line ", - "by rearranging.", -] -``` - -## Black Output - -```py -a = 3 -# fmt: off -b, c = 1, 2 -d = 6 # fmt: skip -e = 5 -# fmt: on -f = [ - "This is a very long line that should be formatted into a clearer line ", - "by rearranging.", -] -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip7.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip7.py.snap deleted file mode 100644 index cd13d5724870e..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip7.py.snap +++ /dev/null @@ -1,45 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip7.py ---- -## Input - -```py -a = "this is some code" -b = 5 #fmt:skip -c = 9 #fmt: skip -d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" #fmt:skip -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,4 +1,4 @@ - a = "this is some code" --b = 5 # fmt:skip -+b = 5 # fmt:skip - c = 9 # fmt: skip - d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip -``` - -## Ruff Output - -```py -a = "this is some code" -b = 5 # fmt:skip -c = 9 # fmt: skip -d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip -``` - -## Black Output - -```py -a = "this is some code" -b = 5 # fmt:skip -c = 9 # fmt: skip -d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip8.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip8.py.snap deleted file mode 100644 index cb1c1a2cf953a..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtskip8.py.snap +++ /dev/null @@ -1,292 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip8.py ---- -## Input - -```py -# Make sure a leading comment is not removed. -def some_func( unformatted, args ): # fmt: skip - print("I am some_func") - return 0 - # Make sure this comment is not removed. - - -# Make sure a leading comment is not removed. -async def some_async_func( unformatted, args): # fmt: skip - print("I am some_async_func") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -class SomeClass( Unformatted, SuperClasses ): # fmt: skip - def some_method( self, unformatted, args ): # fmt: skip - print("I am some_method") - return 0 - - async def some_async_method( self, unformatted, args ): # fmt: skip - print("I am some_async_method") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -if unformatted_call( args ): # fmt: skip - print("First branch") - # Make sure this is not removed. -elif another_unformatted_call( args ): # fmt: skip - print("Second branch") -else : # fmt: skip - print("Last branch") - - -while some_condition( unformatted, args ): # fmt: skip - print("Do something") - - -for i in some_iter( unformatted, args ): # fmt: skip - print("Do something") - - -async def test_async_for(): - async for i in some_async_iter( unformatted, args ): # fmt: skip - print("Do something") - - -try : # fmt: skip - some_call() -except UnformattedError as ex: # fmt: skip - handle_exception() -finally : # fmt: skip - finally_call() - - -with give_me_context( unformatted, args ): # fmt: skip - print("Do something") - - -async def test_async_with(): - async with give_me_async_context( unformatted, args ): # fmt: skip - print("Do something") -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,62 +1,62 @@ - # Make sure a leading comment is not removed. --def some_func( unformatted, args ): # fmt: skip -+def some_func(unformatted, args): # fmt: skip - print("I am some_func") - return 0 - # Make sure this comment is not removed. - - - # Make sure a leading comment is not removed. --async def some_async_func( unformatted, args): # fmt: skip -+async def some_async_func(unformatted, args): # fmt: skip - print("I am some_async_func") - await asyncio.sleep(1) - - - # Make sure a leading comment is not removed. --class SomeClass( Unformatted, SuperClasses ): # fmt: skip -- def some_method( self, unformatted, args ): # fmt: skip -+class SomeClass(Unformatted, SuperClasses): # fmt: skip -+ def some_method(self, unformatted, args): # fmt: skip - print("I am some_method") - return 0 - -- async def some_async_method( self, unformatted, args ): # fmt: skip -+ async def some_async_method(self, unformatted, args): # fmt: skip - print("I am some_async_method") - await asyncio.sleep(1) - - - # Make sure a leading comment is not removed. --if unformatted_call( args ): # fmt: skip -+if unformatted_call(args): # fmt: skip - print("First branch") - # Make sure this is not removed. --elif another_unformatted_call( args ): # fmt: skip -+elif another_unformatted_call(args): # fmt: skip - print("Second branch") --else : # fmt: skip -+else: # fmt: skip - print("Last branch") - - --while some_condition( unformatted, args ): # fmt: skip -+while some_condition(unformatted, args): # fmt: skip - print("Do something") - - --for i in some_iter( unformatted, args ): # fmt: skip -+for i in some_iter(unformatted, args): # fmt: skip - print("Do something") - - - async def test_async_for(): -- async for i in some_async_iter( unformatted, args ): # fmt: skip -+ async for i in some_async_iter(unformatted, args): # fmt: skip - print("Do something") - - --try : # fmt: skip -+try: # fmt: skip - some_call() --except UnformattedError as ex: # fmt: skip -+except UnformattedError as ex: # fmt: skip - handle_exception() --finally : # fmt: skip -+finally: # fmt: skip - finally_call() - - --with give_me_context( unformatted, args ): # fmt: skip -+with give_me_context(unformatted, args): # fmt: skip - print("Do something") - - - async def test_async_with(): -- async with give_me_async_context( unformatted, args ): # fmt: skip -+ async with give_me_async_context(unformatted, args): # fmt: skip - print("Do something") -``` - -## Ruff Output - -```py -# Make sure a leading comment is not removed. -def some_func(unformatted, args): # fmt: skip - print("I am some_func") - return 0 - # Make sure this comment is not removed. - - -# Make sure a leading comment is not removed. -async def some_async_func(unformatted, args): # fmt: skip - print("I am some_async_func") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -class SomeClass(Unformatted, SuperClasses): # fmt: skip - def some_method(self, unformatted, args): # fmt: skip - print("I am some_method") - return 0 - - async def some_async_method(self, unformatted, args): # fmt: skip - print("I am some_async_method") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -if unformatted_call(args): # fmt: skip - print("First branch") - # Make sure this is not removed. -elif another_unformatted_call(args): # fmt: skip - print("Second branch") -else: # fmt: skip - print("Last branch") - - -while some_condition(unformatted, args): # fmt: skip - print("Do something") - - -for i in some_iter(unformatted, args): # fmt: skip - print("Do something") - - -async def test_async_for(): - async for i in some_async_iter(unformatted, args): # fmt: skip - print("Do something") - - -try: # fmt: skip - some_call() -except UnformattedError as ex: # fmt: skip - handle_exception() -finally: # fmt: skip - finally_call() - - -with give_me_context(unformatted, args): # fmt: skip - print("Do something") - - -async def test_async_with(): - async with give_me_async_context(unformatted, args): # fmt: skip - print("Do something") -``` - -## Black Output - -```py -# Make sure a leading comment is not removed. -def some_func( unformatted, args ): # fmt: skip - print("I am some_func") - return 0 - # Make sure this comment is not removed. - - -# Make sure a leading comment is not removed. -async def some_async_func( unformatted, args): # fmt: skip - print("I am some_async_func") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -class SomeClass( Unformatted, SuperClasses ): # fmt: skip - def some_method( self, unformatted, args ): # fmt: skip - print("I am some_method") - return 0 - - async def some_async_method( self, unformatted, args ): # fmt: skip - print("I am some_async_method") - await asyncio.sleep(1) - - -# Make sure a leading comment is not removed. -if unformatted_call( args ): # fmt: skip - print("First branch") - # Make sure this is not removed. -elif another_unformatted_call( args ): # fmt: skip - print("Second branch") -else : # fmt: skip - print("Last branch") - - -while some_condition( unformatted, args ): # fmt: skip - print("Do something") - - -for i in some_iter( unformatted, args ): # fmt: skip - print("Do something") - - -async def test_async_for(): - async for i in some_async_iter( unformatted, args ): # fmt: skip - print("Do something") - - -try : # fmt: skip - some_call() -except UnformattedError as ex: # fmt: skip - handle_exception() -finally : # fmt: skip - finally_call() - - -with give_me_context( unformatted, args ): # fmt: skip - print("Do something") - - -async def test_async_with(): - async with give_me_async_context( unformatted, args ): # fmt: skip - print("Do something") -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap index 0e3bfa106cfe5..dacb0b6cac47d 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap @@ -107,7 +107,7 @@ def __await__(): return (yield) ```diff --- Black +++ Ruff -@@ -65,18 +65,14 @@ +@@ -65,6 +65,7 @@ def spaces2(result=_core.Value(None)): assert fut is self._read_fut, (fut, self._read_fut) @@ -115,22 +115,6 @@ def __await__(): return (yield) def example(session): -- result = ( -- session.query(models.Customer.id) -- .filter( -- models.Customer.account_id == account_id, -- models.Customer.email == email_address, -- ) -- .order_by(models.Customer.id.asc()) -- .all() -- ) -+ result = session.query(models.Customer.id).filter( -+ models.Customer.account_id == account_id, -+ models.Customer.email == email_address, -+ ).order_by(models.Customer.id.asc()).all() - - - def long_lines(): ``` ## Ruff Output @@ -207,10 +191,15 @@ def spaces2(result=_core.Value(None)): def example(session): - result = session.query(models.Customer.id).filter( - models.Customer.account_id == account_id, - models.Customer.email == email_address, - ).order_by(models.Customer.id.asc()).all() + result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, + models.Customer.email == email_address, + ) + .order_by(models.Customer.id.asc()) + .all() + ) def long_lines(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap index 23da8b63513e6..2570ff4de030a 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap @@ -73,22 +73,13 @@ with hmm_but_this_should_get_two_preceding_newlines(): elif os.name == "nt": try: import msvcrt -@@ -45,21 +44,16 @@ - pass - - except ImportError: -- - def i_should_be_followed_by_only_one_newline(): - pass - - elif False: -- +@@ -54,12 +53,10 @@ class IHopeYouAreHavingALovelyDay: def __call__(self): print("i_should_be_followed_by_only_one_newline") - else: -- + def foo(): pass - @@ -146,14 +137,17 @@ elif os.name == "nt": pass except ImportError: + def i_should_be_followed_by_only_one_newline(): pass elif False: + class IHopeYouAreHavingALovelyDay: def __call__(self): print("i_should_be_followed_by_only_one_newline") else: + def foo(): pass diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap deleted file mode 100644 index f08a097d01e43..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap +++ /dev/null @@ -1,213 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/import_spacing.py ---- -## Input - -```py -"""The asyncio package, tracking PEP 3156.""" - -# flake8: noqa - -from logging import ( - WARNING -) -from logging import ( - ERROR, -) -import sys - -# This relies on each of the submodules having an __all__ variable. -from .base_events import * -from .coroutines import * -from .events import * # comment here - -from .futures import * -from .locks import * # comment here -from .protocols import * - -from ..runners import * # comment here -from ..queues import * -from ..streams import * - -from some_library import ( - Just, Enough, Libraries, To, Fit, In, This, Nice, Split, Which, We, No, Longer, Use -) -from name_of_a_company.extremely_long_project_name.component.ttypes import CuteLittleServiceHandlerFactoryyy -from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import * - -from .a.b.c.subprocess import * -from . import (tasks) -from . import (A, B, C) -from . import SomeVeryLongNameAndAllOfItsAdditionalLetters1, \ - SomeVeryLongNameAndAllOfItsAdditionalLetters2 - -__all__ = ( - base_events.__all__ - + coroutines.__all__ - + events.__all__ - + futures.__all__ - + locks.__all__ - + protocols.__all__ - + runners.__all__ - + queues.__all__ - + streams.__all__ - + tasks.__all__ -) -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -38,7 +38,7 @@ - Use, - ) - from name_of_a_company.extremely_long_project_name.component.ttypes import ( -- CuteLittleServiceHandlerFactoryyy, -+ CuteLittleServiceHandlerFactoryyy - ) - from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import * - -``` - -## Ruff Output - -```py -"""The asyncio package, tracking PEP 3156.""" - -# flake8: noqa - -from logging import WARNING -from logging import ( - ERROR, -) -import sys - -# This relies on each of the submodules having an __all__ variable. -from .base_events import * -from .coroutines import * -from .events import * # comment here - -from .futures import * -from .locks import * # comment here -from .protocols import * - -from ..runners import * # comment here -from ..queues import * -from ..streams import * - -from some_library import ( - Just, - Enough, - Libraries, - To, - Fit, - In, - This, - Nice, - Split, - Which, - We, - No, - Longer, - Use, -) -from name_of_a_company.extremely_long_project_name.component.ttypes import ( - CuteLittleServiceHandlerFactoryyy -) -from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import * - -from .a.b.c.subprocess import * -from . import tasks -from . import A, B, C -from . import ( - SomeVeryLongNameAndAllOfItsAdditionalLetters1, - SomeVeryLongNameAndAllOfItsAdditionalLetters2, -) - -__all__ = ( - base_events.__all__ - + coroutines.__all__ - + events.__all__ - + futures.__all__ - + locks.__all__ - + protocols.__all__ - + runners.__all__ - + queues.__all__ - + streams.__all__ - + tasks.__all__ -) -``` - -## Black Output - -```py -"""The asyncio package, tracking PEP 3156.""" - -# flake8: noqa - -from logging import WARNING -from logging import ( - ERROR, -) -import sys - -# This relies on each of the submodules having an __all__ variable. -from .base_events import * -from .coroutines import * -from .events import * # comment here - -from .futures import * -from .locks import * # comment here -from .protocols import * - -from ..runners import * # comment here -from ..queues import * -from ..streams import * - -from some_library import ( - Just, - Enough, - Libraries, - To, - Fit, - In, - This, - Nice, - Split, - Which, - We, - No, - Longer, - Use, -) -from name_of_a_company.extremely_long_project_name.component.ttypes import ( - CuteLittleServiceHandlerFactoryyy, -) -from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import * - -from .a.b.c.subprocess import * -from . import tasks -from . import A, B, C -from . import ( - SomeVeryLongNameAndAllOfItsAdditionalLetters1, - SomeVeryLongNameAndAllOfItsAdditionalLetters2, -) - -__all__ = ( - base_events.__all__ - + coroutines.__all__ - + events.__all__ - + futures.__all__ - + locks.__all__ - + protocols.__all__ - + runners.__all__ - + queues.__all__ - + streams.__all__ - + tasks.__all__ -) -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__multiline_consecutive_open_parentheses_ignore.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__multiline_consecutive_open_parentheses_ignore.py.snap index 8e1c160ff4912..7759ca34bcda6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__multiline_consecutive_open_parentheses_ignore.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__multiline_consecutive_open_parentheses_ignore.py.snap @@ -33,19 +33,17 @@ print( "111" ) # type: ignore ```diff --- Black +++ Ruff -@@ -1,10 +1,8 @@ - # This is a regression test. Issue #3737 - --a = ( # type: ignore -+a = int( # type: ignore # type: ignore +@@ -3,7 +3,9 @@ + a = ( # type: ignore int( # type: ignore -- int( # type: ignore + int( # type: ignore - int(6) # type: ignore -- ) -+ int(6) # type: ignore ++ int( # type: ignore ++ 6 ++ ) + ) ) ) - ``` ## Ruff Output @@ -53,9 +51,13 @@ print( "111" ) # type: ignore ```py # This is a regression test. Issue #3737 -a = int( # type: ignore # type: ignore +a = ( # type: ignore int( # type: ignore - int(6) # type: ignore + int( # type: ignore + int( # type: ignore + 6 + ) + ) ) ) diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__power_op_spacing.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__power_op_spacing.py.snap deleted file mode 100644 index 1a9ad84245f95..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__power_op_spacing.py.snap +++ /dev/null @@ -1,234 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/power_op_spacing.py ---- -## Input - -```py -def function(**kwargs): - t = a**2 + b**3 - return t ** 2 - - -def function_replace_spaces(**kwargs): - t = a **2 + b** 3 + c ** 4 - - -def function_dont_replace_spaces(): - {**a, **b, **c} - - -a = 5**~4 -b = 5 ** f() -c = -(5**2) -d = 5 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5 -g = a.b**c.d -h = 5 ** funcs.f() -i = funcs.f() ** 5 -j = super().name ** 5 -k = [(2**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2**63], [1, 2**63])] -n = count <= 10**5 -o = settings(max_examples=10**6) -p = {(k, k**2): v**2 for k, v in pairs} -q = [10**i for i in range(6)] -r = x**y - -a = 5.0**~4.0 -b = 5.0 ** f() -c = -(5.0**2.0) -d = 5.0 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5.0 -g = a.b**c.d -h = 5.0 ** funcs.f() -i = funcs.f() ** 5.0 -j = super().name ** 5.0 -k = [(2.0**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2.0**63.0], [1.0, 2**63.0])] -n = count <= 10**5.0 -o = settings(max_examples=10**6.0) -p = {(k, k**2): v**2.0 for k, v in pairs} -q = [10.5**i for i in range(6)] - - -# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) -if hasattr(view, "sum_of_weights"): - return np.divide( # type: ignore[no-any-return] - view.variance, # type: ignore[union-attr] - view.sum_of_weights, # type: ignore[union-attr] - out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] - where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr] - ) - -return np.divide( - where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore -) -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -15,7 +15,7 @@ - b = 5 ** f() - c = -(5**2) - d = 5 ** f["hi"] --e = lazy(lambda **kwargs: 5) -+e = lazy(lambda: 5) - f = f() ** 5 - g = a.b**c.d - h = 5 ** funcs.f() -@@ -34,7 +34,7 @@ - b = 5.0 ** f() - c = -(5.0**2.0) - d = 5.0 ** f["hi"] --e = lazy(lambda **kwargs: 5) -+e = lazy(lambda: 5) - f = f() ** 5.0 - g = a.b**c.d - h = 5.0 ** funcs.f() -``` - -## Ruff Output - -```py -def function(**kwargs): - t = a**2 + b**3 - return t**2 - - -def function_replace_spaces(**kwargs): - t = a**2 + b**3 + c**4 - - -def function_dont_replace_spaces(): - {**a, **b, **c} - - -a = 5**~4 -b = 5 ** f() -c = -(5**2) -d = 5 ** f["hi"] -e = lazy(lambda: 5) -f = f() ** 5 -g = a.b**c.d -h = 5 ** funcs.f() -i = funcs.f() ** 5 -j = super().name ** 5 -k = [(2**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2**63], [1, 2**63])] -n = count <= 10**5 -o = settings(max_examples=10**6) -p = {(k, k**2): v**2 for k, v in pairs} -q = [10**i for i in range(6)] -r = x**y - -a = 5.0**~4.0 -b = 5.0 ** f() -c = -(5.0**2.0) -d = 5.0 ** f["hi"] -e = lazy(lambda: 5) -f = f() ** 5.0 -g = a.b**c.d -h = 5.0 ** funcs.f() -i = funcs.f() ** 5.0 -j = super().name ** 5.0 -k = [(2.0**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2.0**63.0], [1.0, 2**63.0])] -n = count <= 10**5.0 -o = settings(max_examples=10**6.0) -p = {(k, k**2): v**2.0 for k, v in pairs} -q = [10.5**i for i in range(6)] - - -# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) -if hasattr(view, "sum_of_weights"): - return np.divide( # type: ignore[no-any-return] - view.variance, # type: ignore[union-attr] - view.sum_of_weights, # type: ignore[union-attr] - out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] - where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr] - ) - -return np.divide( - where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore -) -``` - -## Black Output - -```py -def function(**kwargs): - t = a**2 + b**3 - return t**2 - - -def function_replace_spaces(**kwargs): - t = a**2 + b**3 + c**4 - - -def function_dont_replace_spaces(): - {**a, **b, **c} - - -a = 5**~4 -b = 5 ** f() -c = -(5**2) -d = 5 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5 -g = a.b**c.d -h = 5 ** funcs.f() -i = funcs.f() ** 5 -j = super().name ** 5 -k = [(2**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2**63], [1, 2**63])] -n = count <= 10**5 -o = settings(max_examples=10**6) -p = {(k, k**2): v**2 for k, v in pairs} -q = [10**i for i in range(6)] -r = x**y - -a = 5.0**~4.0 -b = 5.0 ** f() -c = -(5.0**2.0) -d = 5.0 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5.0 -g = a.b**c.d -h = 5.0 ** funcs.f() -i = funcs.f() ** 5.0 -j = super().name ** 5.0 -k = [(2.0**idx, value) for idx, value in pairs] -l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -m = [([2.0**63.0], [1.0, 2**63.0])] -n = count <= 10**5.0 -o = settings(max_examples=10**6.0) -p = {(k, k**2): v**2.0 for k, v in pairs} -q = [10.5**i for i in range(6)] - - -# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) -if hasattr(view, "sum_of_weights"): - return np.divide( # type: ignore[no-any-return] - view.variance, # type: ignore[union-attr] - view.sum_of_weights, # type: ignore[union-attr] - out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] - where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr] - ) - -return np.divide( - where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore -) -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap index 26fc695ecbb9f..428ca61376081 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap @@ -93,13 +93,12 @@ async def main(): ```diff --- Black +++ Ruff -@@ -21,7 +21,10 @@ +@@ -21,7 +21,9 @@ # Check comments async def main(): - await asyncio.sleep(1) # Hello -+ await ( -+ # Hello ++ await ( # Hello + asyncio.sleep(1) + ) @@ -133,8 +132,7 @@ async def main(): # Check comments async def main(): - await ( - # Hello + await ( # Hello asyncio.sleep(1) ) diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_parens.py.snap deleted file mode 100644 index 9cb91d4c09e58..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_parens.py.snap +++ /dev/null @@ -1,281 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_parens.py ---- -## Input - -```py -x = (1) -x = (1.2) - -data = ( - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -).encode() - -async def show_status(): - while True: - try: - if report_host: - data = ( - f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ).encode() - except Exception as e: - pass - -def example(): - return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")) - - -def example1(): - return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111)) - - -def example1point5(): - return ((((((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111)))))) - - -def example2(): - return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")) - - -def example3(): - return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111)) - - -def example4(): - return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((True)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) - - -def example5(): - return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) - - -def example6(): - return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]}))))))))) - - -def example7(): - return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20000000000000000000]}))))))))) - - -def example8(): - return (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((None))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -11,8 +11,10 @@ - try: - if report_host: - data = ( -- f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -- ).encode() -+ ( -+ f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -+ ).encode() -+ ) - except Exception as e: - pass - -@@ -30,15 +32,11 @@ - - - def example2(): -- return ( -- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -- ) -+ return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - - - def example3(): -- return ( -- 1111111111111111111111111111111111111111111111111111111111111111111111111111111 -- ) -+ return 1111111111111111111111111111111111111111111111111111111111111111111111111111111 - - - def example4(): -``` - -## Ruff Output - -```py -x = 1 -x = 1.2 - -data = ( - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -).encode() - - -async def show_status(): - while True: - try: - if report_host: - data = ( - ( - f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ).encode() - ) - except Exception as e: - pass - - -def example(): - return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - - -def example1(): - return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - - -def example1point5(): - return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - - -def example2(): - return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - - -def example3(): - return 1111111111111111111111111111111111111111111111111111111111111111111111111111111 - - -def example4(): - return True - - -def example5(): - return () - - -def example6(): - return {a: a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]} - - -def example7(): - return { - a: a - for a in [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20000000000000000000, - ] - } - - -def example8(): - return None -``` - -## Black Output - -```py -x = 1 -x = 1.2 - -data = ( - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -).encode() - - -async def show_status(): - while True: - try: - if report_host: - data = ( - f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ).encode() - except Exception as e: - pass - - -def example(): - return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - - -def example1(): - return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - - -def example1point5(): - return 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - - -def example2(): - return ( - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ) - - -def example3(): - return ( - 1111111111111111111111111111111111111111111111111111111111111111111111111111111 - ) - - -def example4(): - return True - - -def example5(): - return () - - -def example6(): - return {a: a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]} - - -def example7(): - return { - a: a - for a in [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20000000000000000000, - ] - } - - -def example8(): - return None -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__return_annotation_brackets.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__return_annotation_brackets.py.snap index c35111a8b1b18..552ca4576bfc3 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__return_annotation_brackets.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__return_annotation_brackets.py.snap @@ -100,26 +100,26 @@ def foo() -> tuple[int, int, int,]: ```diff --- Black +++ Ruff -@@ -26,7 +26,9 @@ - return 2 * a +@@ -22,11 +22,19 @@ + # Don't lose the comments -def double(a: int) -> int: # Hello -+def double(a: int) -> ( -+ int # Hello ++def double( ++ a: int ++) -> ( # Hello ++ int +): return 2 * a -@@ -54,7 +56,9 @@ - a: int, - b: int, - c: int, --) -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds: +-def double(a: int) -> int: # Hello ++def double( ++ a: int +) -> ( -+ intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds ++ int # Hello +): - return 2 + return 2 * a ``` @@ -151,11 +151,17 @@ def double(a: int) -> int: # Don't lose the comments -def double(a: int) -> int: # Hello +def double( + a: int +) -> ( # Hello + int +): return 2 * a -def double(a: int) -> ( +def double( + a: int +) -> ( int # Hello ): return 2 * a @@ -185,9 +191,7 @@ def foo( a: int, b: int, c: int, -) -> ( - intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds -): +) -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds: return 2 diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__torture.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__torture.py.snap index 69341cf62750c..f44e1053f0b4b 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__torture.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__torture.py.snap @@ -50,14 +50,15 @@ assert ( ) # assert sort_by_dependency( -@@ -25,9 +25,7 @@ +@@ -25,9 +25,9 @@ class A: def foo(self): for _ in range(10): - aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc( -- xxxxxxxxxxxx ++ aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc( # pylint: disable=no-member + xxxxxxxxxxxx - ) # pylint: disable=no-member -+ aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc(xxxxxxxxxxxx) # pylint: disable=no-member ++ ) def test(self, othr): @@ -93,7 +94,9 @@ importA class A: def foo(self): for _ in range(10): - aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc(xxxxxxxxxxxx) # pylint: disable=no-member + aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc( # pylint: disable=no-member + xxxxxxxxxxxx + ) def test(self, othr): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__trailing_commas_in_leading_parts.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__trailing_commas_in_leading_parts.py.snap index 6a978187fcc96..514ea6258ad1e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__trailing_commas_in_leading_parts.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__trailing_commas_in_leading_parts.py.snap @@ -56,14 +56,18 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( # Example from https://github.com/psf/black/issues/3229 -@@ -45,6 +43,4 @@ +@@ -43,8 +41,6 @@ + ) + # Regression test for https://github.com/psf/black/issues/3414. - assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( - xxxxxxxxx +-assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( +- xxxxxxxxx -).xxxxxxxxxxxxxxxxxx(), ( - "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -) -+).xxxxxxxxxxxxxxxxxx(), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ++assert ( ++ xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx() ++), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ## Ruff Output @@ -112,9 +116,9 @@ assert ( ) # Regression test for https://github.com/psf/black/issues/3414. -assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( - xxxxxxxxx -).xxxxxxxxxxxxxxxxxx(), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +assert ( + xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx() +), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/format@docstring.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@docstring.py.snap new file mode 100644 index 0000000000000..0a3c9a62a6e25 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@docstring.py.snap @@ -0,0 +1,448 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring.py +--- +## Input +```py +def single_line_backslashes1(): + """ content\ """ + return + + +def single_line_backslashes2(): + """ content\\ """ + return + + +def single_line_backslashes3(): + """ content\\\ """ + return + + +def multiline_backslashes1(): + """This is a docstring with + some lines of text\ """ + return + + +def multiline_backslashes2(): + """This is a docstring with + some lines of text\\ """ + return + + +def multiline_backslashes3(): + """This is a docstring with + some lines of text\\\ """ + return + + +def multiple_negatively_indented_docstring_lines(): + """a + b + c + d + e + """ + + +def overindentend_docstring(): + """a + over-indented + """ + + +def comment_before_docstring(): + # don't lose this function comment ... + """Does nothing. + + But it has comments + """ # ... neither lose this function comment + + +class CommentBeforeDocstring(): + # don't lose this class comment ... + """Empty class. + + But it has comments + """ # ... neither lose this class comment + + +class IndentMeSome: + def doc_string_without_linebreak_after_colon(self): """ This is somewhat strange + a + b + We format this a is the docstring had started properly indented on the next + line if the target indentation. This may we incorrect since source and target + indentation can be incorrect, but this is also an edge case. + """ + + +class IgnoreImplicitlyConcatenatedStrings: + """""" "" + + +def docstring_that_ends_with_quote_and_a_line_break1(): + """ + he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break2(): + """he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break3(): + """he said "the news of my death have been greatly exaggerated" + + """ + + +class TabbedIndent: + def tabbed_indent(self): + """check for correct tabbed formatting + ^^^^^^^^^^ + Normal indented line + - autor + """ +``` + +## Outputs +### Output 1 +``` +indent-style = Spaces, size: 4 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def single_line_backslashes1(): + """content\ """ + return + + +def single_line_backslashes2(): + """content\\""" + return + + +def single_line_backslashes3(): + """content\\\ """ + return + + +def multiline_backslashes1(): + """This is a docstring with + some lines of text\ """ + return + + +def multiline_backslashes2(): + """This is a docstring with + some lines of text\\""" + return + + +def multiline_backslashes3(): + """This is a docstring with + some lines of text\\\ """ + return + + +def multiple_negatively_indented_docstring_lines(): + """a + b + c + d + e + """ + + +def overindentend_docstring(): + """a + over-indented + """ + + +def comment_before_docstring(): + # don't lose this function comment ... + """Does nothing. + + But it has comments + """ # ... neither lose this function comment + + +class CommentBeforeDocstring: + # don't lose this class comment ... + """Empty class. + + But it has comments + """ # ... neither lose this class comment + + +class IndentMeSome: + def doc_string_without_linebreak_after_colon(self): + """This is somewhat strange + a + b + We format this a is the docstring had started properly indented on the next + line if the target indentation. This may we incorrect since source and target + indentation can be incorrect, but this is also an edge case. + """ + + +class IgnoreImplicitlyConcatenatedStrings: + """""" "" + + +def docstring_that_ends_with_quote_and_a_line_break1(): + """ + he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break2(): + """he said "the news of my death have been greatly exaggerated" """ + + +def docstring_that_ends_with_quote_and_a_line_break3(): + """he said "the news of my death have been greatly exaggerated" """ + + +class TabbedIndent: + def tabbed_indent(self): + """check for correct tabbed formatting + ^^^^^^^^^^ + Normal indented line + - autor + """ +``` + + +### Output 2 +``` +indent-style = Spaces, size: 2 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def single_line_backslashes1(): + """content\ """ + return + + +def single_line_backslashes2(): + """content\\""" + return + + +def single_line_backslashes3(): + """content\\\ """ + return + + +def multiline_backslashes1(): + """This is a docstring with + some lines of text\ """ + return + + +def multiline_backslashes2(): + """This is a docstring with + some lines of text\\""" + return + + +def multiline_backslashes3(): + """This is a docstring with + some lines of text\\\ """ + return + + +def multiple_negatively_indented_docstring_lines(): + """a + b + c + d + e + """ + + +def overindentend_docstring(): + """a + over-indented + """ + + +def comment_before_docstring(): + # don't lose this function comment ... + """Does nothing. + + But it has comments + """ # ... neither lose this function comment + + +class CommentBeforeDocstring: + # don't lose this class comment ... + """Empty class. + + But it has comments + """ # ... neither lose this class comment + + +class IndentMeSome: + def doc_string_without_linebreak_after_colon(self): + """This is somewhat strange + a + b + We format this a is the docstring had started properly indented on the next + line if the target indentation. This may we incorrect since source and target + indentation can be incorrect, but this is also an edge case. + """ + + +class IgnoreImplicitlyConcatenatedStrings: + """""" "" + + +def docstring_that_ends_with_quote_and_a_line_break1(): + """ + he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break2(): + """he said "the news of my death have been greatly exaggerated" """ + + +def docstring_that_ends_with_quote_and_a_line_break3(): + """he said "the news of my death have been greatly exaggerated" """ + + +class TabbedIndent: + def tabbed_indent(self): + """check for correct tabbed formatting + ^^^^^^^^^^ + Normal indented line + - autor + """ +``` + + +### Output 3 +``` +indent-style = Tab +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def single_line_backslashes1(): + """content\ """ + return + + +def single_line_backslashes2(): + """content\\""" + return + + +def single_line_backslashes3(): + """content\\\ """ + return + + +def multiline_backslashes1(): + """This is a docstring with + some lines of text\ """ + return + + +def multiline_backslashes2(): + """This is a docstring with + some lines of text\\""" + return + + +def multiline_backslashes3(): + """This is a docstring with + some lines of text\\\ """ + return + + +def multiple_negatively_indented_docstring_lines(): + """a + b + c + d + e + """ + + +def overindentend_docstring(): + """a + over-indented + """ + + +def comment_before_docstring(): + # don't lose this function comment ... + """Does nothing. + + But it has comments + """ # ... neither lose this function comment + + +class CommentBeforeDocstring: + # don't lose this class comment ... + """Empty class. + + But it has comments + """ # ... neither lose this class comment + + +class IndentMeSome: + def doc_string_without_linebreak_after_colon(self): + """This is somewhat strange + a + b + We format this a is the docstring had started properly indented on the next + line if the target indentation. This may we incorrect since source and target + indentation can be incorrect, but this is also an edge case. + """ + + +class IgnoreImplicitlyConcatenatedStrings: + """""" "" + + +def docstring_that_ends_with_quote_and_a_line_break1(): + """ + he said "the news of my death have been greatly exaggerated" + """ + + +def docstring_that_ends_with_quote_and_a_line_break2(): + """he said "the news of my death have been greatly exaggerated" """ + + +def docstring_that_ends_with_quote_and_a_line_break3(): + """he said "the news of my death have been greatly exaggerated" """ + + +class TabbedIndent: + def tabbed_indent(self): + """check for correct tabbed formatting + ^^^^^^^^^^ + Normal indented line + - autor + """ +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap index f1a5dbb035c50..14f17fc6631b0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap @@ -112,7 +112,25 @@ x6 = ( a.b ) +# regression: https://github.com/astral-sh/ruff/issues/6181 +(# +()).a +( + ( + a # trailing end-of-line + # trailing own-line + ) # dangling before dot end-of-line + .b # trailing end-of-line +) + +( + ( + a + ) + # dangling before dot own-line + .b +) ``` ## Output @@ -122,29 +140,30 @@ from argparse import Namespace a = Namespace() ( - a. + a # comment - b # trailing comment + .b # trailing comment ) ( - a. + a # comment - b # trailing dot comment # trailing identifier comment + .b # trailing dot comment # trailing identifier comment ) ( - a. + a # comment - b # trailing identifier comment + .b # trailing identifier comment ) ( - a. + a # comment + . # trailing dot comment # in between - b # trailing dot comment # trailing identifier comment + b # trailing identifier comment ) @@ -155,10 +174,11 @@ a.aaaaaaaaaaaaaaaaaaaaa.lllllllllllllllllllllllllllloooooooooong.chaaaaaaaaaaaaa # chain if and only if we need them, that is if there are own line comments inside # the chain. x1 = ( - a.b. + a.b # comment 1 + . # comment 2 # comment 3 - c.d # comment 2 + c.d ) x20 = a.b @@ -167,27 +187,33 @@ x21 = ( a.b # trailing name end-of-line ) x22 = ( - a. + a # outermost leading own line - b # outermost trailing end-of-line + .b # outermost trailing end-of-line ) x31 = ( - a. + a # own line between nodes 1 + .b +) +x321 = ( + a. # end-of-line dot comment b ) -x321 = a.b # end-of-line dot comment -x322 = a.b.c # end-of-line dot comment 2 +x322 = ( + a. # end-of-line dot comment 2 + b.c +) x331 = ( a. # own line between nodes 3 b ) x332 = ( - "". + "" # own line between nodes - find + .find ) x8 = (a + a).b @@ -200,6 +226,25 @@ x6 = ( # Check assumption with enclosing nodes a.b ) + +# regression: https://github.com/astral-sh/ruff/issues/6181 +( # + () +).a + +( + ( + a # trailing end-of-line + # trailing own-line + ) # dangling before dot end-of-line + .b # trailing end-of-line +) + +( + (a) + # dangling before dot own-line + .b +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap index 61499e20e362e..172b318812e4c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap @@ -217,6 +217,17 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}: log(self.price / self.strike) + (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time ) / self.sigmaT + +# Stability with end-of-line comments between empty tuples and bin op +x = () - (# +) +x = ( + () + - () # +) +x = ( + () - () # +) ``` ## Output @@ -488,6 +499,19 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}: log(self.price / self.strike) + (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time ) / self.sigmaT + +# Stability with end-of-line comments between empty tuples and bin op +x = ( + () + - ( # + ) +) +x = ( + () - () # +) +x = ( + () - () # +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary_implicit_string.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary_implicit_string.py.snap index 8176cc6fdfecc..a87ae3d9d87c0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary_implicit_string.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary_implicit_string.py.snap @@ -180,7 +180,8 @@ def test(): ", %s unmodified" % unmodified_count if collected["unmodified"] else "" ), "post_processed": ( - collected["post_processed"] and ", %s post-processed" % post_processed_count + collected["post_processed"] + and ", %s post-processed" % post_processed_count or "" ), } diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap index 979f6fb80509d..01ae09af34844 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap @@ -68,6 +68,38 @@ if ( and [dddddddddddddd, eeeeeeeeee, fffffffffffffff] ): pass + +# Regression test for https://github.com/astral-sh/ruff/issues/6068 +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or numpy and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and numpy or isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy or isinstance(ccccccccccc, dddddd) +): + pass + + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) or (xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy) and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) and (xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy) or isinstance(ccccccccccc, dddddd) +): + pass ``` ## Output @@ -136,6 +168,58 @@ if ( and [dddddddddddddd, eeeeeeeeee, fffffffffffffff] ): pass + +# Regression test for https://github.com/astral-sh/ruff/issues/6068 +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + or numpy + and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + and numpy + or isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + or xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + and xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + or isinstance(ccccccccccc, dddddd) +): + pass + + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + or ( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + ) + and isinstance(ccccccccccc, dddddd) +): + pass + +if not ( + isinstance(aaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbb) + and ( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + ) + or isinstance(ccccccccccc, dddddd) +): + pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap index bac556ce5f248..e3771e0389c0a 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap @@ -58,7 +58,7 @@ f( hey_this_is_a_very_long_call=1, it_has_funny_attributes_asdf_asdf=1, too_long_for_the_line=1, really=True ) -# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +# Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) result = ( session.query(models.Customer.id) .filter( @@ -92,6 +92,125 @@ f( f( a.very_long_function_function_that_is_so_long_that_it_expands_the_parent_but_its_only_a_single_argument() ) + +f( # abc +) + +f( # abc + # abc +) + +f( + # abc +) + +f ( # abc + 1 +) + +f ( + # abc + 1 +) + +f ( + 1 + # abc +) + +threshold_date = datetime.datetime.now() - datetime.timedelta( # comment + days=threshold_days_threshold_days +) + +# Parenthesized and opening-parenthesis comments +func( + (x for x in y) +) + +func( # outer comment + (x for x in y) +) + +func( + ( # inner comment + x for x in y + ) +) + +func( + ( + # inner comment + x for x in y + ) +) + +func( # outer comment + ( # inner comment + 1 + ) +) + +func( + # outer comment + ( # inner comment + x for x in y + ) +) + + +func( + ( # inner comment + [] + ) +) + +func( + # outer comment + ( # inner comment + [] + ) +) + +# Comments between the function and its arguments +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # baz + # awkward comment + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + (foo # awkward comment + ) + () + .bbbbbbbbbbbbbbbb +) + +aaa = ( + ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + ) + () + .bbbbbbbbbbbbbbbb +) ``` ## Output @@ -137,8 +256,9 @@ f( these_arguments_have_values_that_need_to_break_because_they_are_too_long3=session, ) -f() -# dangling comment +f( + # dangling comment +) f(only=1, short=1, arguments=1) @@ -152,11 +272,16 @@ f( really=True, ) -# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) -result = session.query(models.Customer.id).filter( - models.Customer.account_id == 10000, - models.Customer.email == "user@example.org", -).order_by(models.Customer.id.asc()).all() +# Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == 10000, + models.Customer.email == "user@example.org", + ) + .order_by(models.Customer.id.asc()) + .all() +) # TODO(konstin): Black has this special case for comment placement where everything stays in one line f("aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa") @@ -177,6 +302,112 @@ f( f( a.very_long_function_function_that_is_so_long_that_it_expands_the_parent_but_its_only_a_single_argument() ) + +f( # abc +) + +f( # abc + # abc +) + +f( + # abc +) + +f( # abc + 1 +) + +f( + # abc + 1 +) + +f( + 1 + # abc +) + +threshold_date = datetime.datetime.now() - datetime.timedelta( # comment + days=threshold_days_threshold_days +) + +# Parenthesized and opening-parenthesis comments +func(x for x in y) + +func( # outer comment + x for x in y +) + +func( + ( # inner comment + x for x in y + ) +) + +func( + # inner comment + x + for x in y +) + +func( # outer comment + ( # inner comment + 1 + ) +) + +func( + # outer comment + ( # inner comment + x for x in y + ) +) + + +func( + ( # inner comment + [] + ) +) + +func( + # outer comment + ( # inner comment + [] + ) +) + +# Comments between the function and its arguments +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + ().bbbbbbbbbbbbbbbb +) + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment + ().bbbbbbbbbbbbbbbb +) + + +aaa = ( + # bar + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # baz + # awkward comment + ().bbbbbbbbbbbbbbbb +) + +aaa = ( + foo # awkward comment +)().bbbbbbbbbbbbbbbb + +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + # awkward comment +)().bbbbbbbbbbbbbbbb ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap index f62138f5d9b97..e47b22e60a347 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap @@ -65,6 +65,58 @@ return 1 == 2 and ( >= c ) ] + +def f(): + return ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKC", s2).casefold() + ) + +# Call expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = aaaaaaaaaaact_id == self.get_content_type( + obj=rel_obj, using=instance._state.db +) + +# Call expressions with trailing subscripts. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +# Subscripts expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) + +ct_match = ( + {aaaaaaaaaaaaaaaa} == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) + +ct_match = ( + (aaaaaaaaaaaaaaaa) == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) ``` ## Output @@ -171,6 +223,61 @@ return 1 == 2 and ( >= c ) ] + + +def f(): + return ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKC", s2).casefold() + ) + + +# Call expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db).id +) + +ct_match = {aaaaaaaaaaaaaaaa} == self.get_content_type( + obj=rel_obj, using=instance._state.db +).id + +ct_match = (aaaaaaaaaaaaaaaa) == self.get_content_type( + obj=rel_obj, using=instance._state.db +).id + +ct_match = aaaaaaaaaaact_id == self.get_content_type( + obj=rel_obj, using=instance._state.db +) + +# Call expressions with trailing subscripts. + +ct_match = ( + aaaaaaaaaaact_id == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] +) + +ct_match = { + aaaaaaaaaaaaaaaa +} == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] + +ct_match = ( + aaaaaaaaaaaaaaaa +) == self.get_content_type(obj=rel_obj, using=instance._state.db)[id] + +# Subscripts expressions with trailing attributes. + +ct_match = ( + aaaaaaaaaaact_id + == self.get_content_type[obj, rel_obj, using, instance._state.db].id +) + +ct_match = { + aaaaaaaaaaaaaaaa +} == self.get_content_type[obj, rel_obj, using, instance._state.db].id + +ct_match = ( + aaaaaaaaaaaaaaaa +) == self.get_content_type[obj, rel_obj, using, instance._state.db].id ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__dict.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__dict.py.snap index 300074af734b5..a5b6c5e896034 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__dict.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__dict.py.snap @@ -70,8 +70,7 @@ x={ # dangling end of line comment ## Output ```py # before -{ - # open +{ # open key: value # key # colon # value } # close # after diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__dict_comp.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__dict_comp.py.snap index 651e8e56449e5..4d725fc27c17c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__dict_comp.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__dict_comp.py.snap @@ -92,6 +92,29 @@ selected_choices = { k: str(v) for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values } + +{ + k: v + for ( # foo + + x, aaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaay) in z +} + +a = { + k: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +a = { + k: [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +aaaaaaaaaaaaaaaaaaaaa = { + k: o for o in self.registry.values if o.__class__ is not ModelAdmin +} ``` ## Output @@ -201,11 +224,9 @@ selected_choices = { } # Leading -{ - # Leading +{ # Leading k: v # Trailing - for a, a, a, a, a, a, a, a, a, a, ( - # Trailing + for a, a, a, a, a, a, a, a, a, a, ( # Trailing a, a, a, @@ -241,6 +262,34 @@ selected_choices = { for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values } + +{ + k: v + for ( # foo + x, + aaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaay, + ) in z +} + +a = { + k: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +a = { + k: [ + 1, + 2, + 3, + ] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +} + +aaaaaaaaaaaaaaaaaaaaa = { + k: o for o in self.registry.values if o.__class__ is not ModelAdmin +} ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__fstring.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__fstring.py.snap new file mode 100644 index 0000000000000..aa3f0a5133aae --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__fstring.py.snap @@ -0,0 +1,82 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py +--- +## Input +```py +( + f'{one}' + f'{two}' +) + + +rf"Not-so-tricky \"quote" + +# Regression test for fstrings dropping comments +result_f = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + f' File "{__file__}", line {lineno_f+1}, in f\n' + ' f()\n' + # XXX: The following line changes depending on whether the tests + # are run through the interactive interpreter or with -m + # It also varies depending on the platform (stack size) + # Fortunately, we don't care about exactness here, so we use regex + r' \[Previous line repeated (\d+) more times\]' '\n' + 'RecursionError: maximum recursion depth exceeded\n' +) + + +# Regression for fstring dropping comments that were accidentally attached to +# an expression inside a formatted value +( + f'{1}' + # comment + '' +) +``` + +## Output +```py +(f"{one}" f"{two}") + + +rf"Not-so-tricky \"quote" + +# Regression test for fstrings dropping comments +result_f = ( + "Traceback (most recent call last):\n" + f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' + " f()\n" + f' File "{__file__}", line {lineno_f+1}, in f\n' + " f()\n" + f' File "{__file__}", line {lineno_f+1}, in f\n' + " f()\n" + f' File "{__file__}", line {lineno_f+1}, in f\n' + " f()\n" + # XXX: The following line changes depending on whether the tests + # are run through the interactive interpreter or with -m + # It also varies depending on the platform (stack size) + # Fortunately, we don't care about exactness here, so we use regex + r" \[Previous line repeated (\d+) more times\]" + "\n" + "RecursionError: maximum recursion depth exceeded\n" +) + + +# Regression for fstring dropping comments that were accidentally attached to +# an expression inside a formatted value +( + f"{1}" + # comment + "" +) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__generator_exp.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__generator_exp.py.snap index 2bc38c773cb06..ed11b4724c924 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__generator_exp.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__generator_exp.py.snap @@ -31,6 +31,28 @@ len( # trailing ) ) + +len( + # leading + a for b in c + # trailing +) + +a = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +a = ( + [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +aaaaaaaaaaaaaaaaaaaaa = ( + o for o in self.registry.values if o.__class__ is not ModelAdmin +) ``` ## Output @@ -56,12 +78,40 @@ f((1) for _ in (a)) # black keeps these atm, but intends to remove them in the future: # https://github.com/psf/black/issues/2943 +len( + ( # leading + a + for b in c + # trailing + ) +) + len( # leading a for b in c # trailing ) + +a = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +a = ( + [ + 1, + 2, + 3, + ] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +) + +aaaaaaaaaaaaaaaaaaaaa = ( + o for o in self.registry.values if o.__class__ is not ModelAdmin +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__joined_string.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__joined_string.py.snap deleted file mode 100644 index d9f8f4313d993..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__joined_string.py.snap +++ /dev/null @@ -1,25 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py ---- -## Input -```py -( - f'{one}' - f'{two}' -) - - -rf"Not-so-tricky \"quote" -``` - -## Output -```py -(f"{one}" f"{two}") - - -rf'Not-so-tricky "quote' -``` - - - diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap index fbc6c3ac760cf..73e3bcc04d24c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap @@ -62,12 +62,16 @@ lambda x: lambda y: lambda z: ( z) # Trailing # Trailing - a = ( lambda # Dangling : 1 ) +a = ( + lambda x # Dangling + , y: 1 +) + # Regression test: lambda empty arguments ranges were too long, leading to unstable # formatting (lambda:(# @@ -81,6 +85,45 @@ def f( # ...but we do preserve a trailing comma after the arguments a = lambda b,: 0 + +lambda a,: 0 +lambda *args,: 0 +lambda **kwds,: 0 +lambda a, *args,: 0 +lambda a, **kwds,: 0 +lambda *args, b,: 0 +lambda *, b,: 0 +lambda *args, **kwds,: 0 +lambda a, *args, b,: 0 +lambda a, *, b,: 0 +lambda a, *args, **kwds,: 0 +lambda *args, b, **kwds,: 0 +lambda *, b, **kwds,: 0 +lambda a, *args, b, **kwds,: 0 +lambda a, *, b, **kwds,: 0 +lambda a, /: a +lambda a, /, c: a + +# Dangling comments without parameters. +( + lambda + : # 3 + None +) + +( + lambda + # 3 + : None +) + +( + lambda # 1 + # 2 + : # 3 + # 4 + None # 5 +) ``` ## Output @@ -141,9 +184,14 @@ lambda x: lambda y: lambda z: ( ) # Trailing # Trailing +a = ( + lambda: # Dangling + 1 +) a = ( - lambda: 1 # Dangling + lambda x, # Dangling + y: 1 ) # Regression test: lambda empty arguments ranges were too long, leading to unstable @@ -163,6 +211,43 @@ def f( # ...but we do preserve a trailing comma after the arguments a = lambda b,: 0 + +lambda a,: 0 +lambda *args,: 0 +lambda **kwds,: 0 +lambda a, *args,: 0 +lambda a, **kwds,: 0 +lambda *args, b,: 0 +lambda *, b,: 0 +lambda *args, **kwds,: 0 +lambda a, *args, b,: 0 +lambda a, *, b,: 0 +lambda a, *args, **kwds,: 0 +lambda *args, b, **kwds,: 0 +lambda *, b, **kwds,: 0 +lambda a, *args, b, **kwds,: 0 +lambda a, *, b, **kwds,: 0 +lambda a, /: a +lambda a, /, c: a + +# Dangling comments without parameters. +( + lambda: # 3 + None +) + +( + lambda: # 3 + None +) + +( + lambda: # 1 + # 2 + # 3 + # 4 + None # 5 +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__list.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__list.py.snap index e21436a052668..1d00f6ae54102 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__list.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__list.py.snap @@ -27,6 +27,43 @@ b3 = [ aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa ] + +# Comment placement in non-empty lists +c1 = [ # trailing open bracket + # leading item + 1, + + # between + + 2, # trailing item + # leading close bracket +] # trailing close bracket + + +[ # end-of-line comment +] + +[ # end-of-line comment + # own-line comment +] + +[ # end-of-line comment + 1 +] + +[ # inner comment + first, + second, + third +] # outer comment + +[ # inner comment + # own-line comment + ( # end-of-line comment + # own-line comment + first, + ), +] # outer comment ``` ## Output @@ -54,6 +91,41 @@ b3 = [ aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, ] + +# Comment placement in non-empty lists +c1 = [ # trailing open bracket + # leading item + 1, + # between + 2, # trailing item + # leading close bracket +] # trailing close bracket + + +[ # end-of-line comment +] + +[ # end-of-line comment + # own-line comment +] + +[ # end-of-line comment + 1 +] + +[ # inner comment + first, + second, + third, +] # outer comment + +[ # inner comment + # own-line comment + ( # end-of-line comment + # own-line comment + first, + ), +] # outer comment ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__list_comp.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__list_comp.py.snap index f480119b8e16c..57e59f3c0458c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__list_comp.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__list_comp.py.snap @@ -62,7 +62,24 @@ selected_choices = [ # Tuples with BinOp [i for i in (aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc)] -[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b]``` +[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b] + +a = [ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +a = [ + [1, 2, 3,] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +aaaaaaaaaaaaaaaaaaaaa = [ + o for o in self.registry.values if o.__class__ is not ModelAdmin +] +``` ## Output ```py @@ -141,6 +158,26 @@ selected_choices = [ ) for i in b ] + +a = [ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +a = [ + [ + 1, + 2, + 3, + ] + for f in bbbbbbbbbbbbbbb + if f not in ccccccccccc +] + +aaaaaaaaaaaaaaaaaaaaa = [ + o for o in self.registry.values if o.__class__ is not ModelAdmin +] ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__named_expr.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__named_expr.py.snap index 018df04c7204a..68a74972a050d 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__named_expr.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__named_expr.py.snap @@ -14,6 +14,52 @@ if ( ): pass +if ( + # 1 + x # 2 + := # 3 + (y) # 4 +): + pass + +if ( + # 1 + x # 2 + := # 3 + (y) # 4 + # 5 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + y # 4 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + ( # 4 + y # 5 + ) # 6 +): + pass + +if ( + x # 2 + := # 3 + y +): + pass + y0 = (y1 := f(x)) f(x:=y, z=True) @@ -42,6 +88,21 @@ except (e := Exception): (x := 1) (x := 1) + (y := 2) + +with (x := 1): + pass + + +def f(): + yield (x := 1) + + +def f(): + yield from (x := 1) + + +async def f(): + await (x := 1) ``` ## Output @@ -50,7 +111,55 @@ y = 1 if ( # 1 - x := y # 2 # 3 # 4 + x # 2 + := # 3 + y # 4 +): + pass + +if ( + # 1 + x # 2 + := # 3 + (y) # 4 +): + pass + +if ( + # 1 + x # 2 + := # 3 + (y) # 4 + # 5 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + y # 4 +): + pass + +if ( + # 1 + x # 2 + # 2.5 + := # 3 + # 3.5 + ( # 4 + y # 5 + ) # 6 +): + pass + +if ( + x # 2 + := # 3 + y ): pass @@ -82,6 +191,21 @@ except (e := Exception): (x := 1) (x := 1) + (y := 2) + +with (x := 1): + pass + + +def f(): + yield (x := 1) + + +def f(): + yield from (x := 1) + + +async def f(): + await (x := 1) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__split_empty_brackets.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__split_empty_brackets.py.snap new file mode 100644 index 0000000000000..c923784d048e3 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__split_empty_brackets.py.snap @@ -0,0 +1,197 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/split_empty_brackets.py +--- +## Input +```py +# Expressions with empty parentheses. +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(1) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(0) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold(1) +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(1) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold(1) +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold( + # foo + ) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold( + # foo + ) +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [1].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [1].unicodedata.normalize("NFKC", s1).casefold() + == [].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [1].unicodedata.normalize("NFKC", s1).casefold() + == [1].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {1}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {1}.unicodedata.normalize("NFKC", s1).casefold() + == {}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {1}.unicodedata.normalize("NFKC", s1).casefold() + == {1}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + ([]).unicodedata.normalize("NFKC", s1).casefold() + == ([]).unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +return await self.http_client.fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +return await self.http_client().fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +return await self().http_client().fetch( + f"http://127.0.0.1:{self.port}{path}", method=method, **kwargs, +) + +response = await sync_to_async( + lambda: self.django_handler.get_response(request), thread_sensitive=True +)() +``` + +## Output +```py +# Expressions with empty parentheses. +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold(1) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = unicodedata.normalize("NFKC", s1).casefold(0) == unicodedata.normalize( + "NFKCNFKCNFKCNFKCNFKC", s2 +).casefold(1) + +ct_match = unicodedata.normalize("NFKC", s1).casefold(1) == unicodedata.normalize( + "NFKCNFKCNFKCNFKCNFKC", s2 +).casefold(1) + +ct_match = ( + unicodedata.normalize("NFKC", s1).casefold( + # foo + ) + == unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold( + # foo + ) +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + [].unicodedata.normalize("NFKC", s1).casefold() + == [1].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = [1].unicodedata.normalize("NFKC", s1).casefold() == [].unicodedata.normalize( + "NFKCNFKCNFKCNFKCNFKC", s2 +).casefold() + +ct_match = [1].unicodedata.normalize("NFKC", s1).casefold() == [ + 1 +].unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = ( + {}.unicodedata.normalize("NFKC", s1).casefold() + == {1}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() +) + +ct_match = {1}.unicodedata.normalize("NFKC", s1).casefold() == {}.unicodedata.normalize( + "NFKCNFKCNFKCNFKCNFKC", s2 +).casefold() + +ct_match = {1}.unicodedata.normalize("NFKC", s1).casefold() == { + 1 +}.unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() + +ct_match = ([]).unicodedata.normalize("NFKC", s1).casefold() == ( + [] +).unicodedata.normalize("NFKCNFKCNFKCNFKCNFKC", s2).casefold() + +return await self.http_client.fetch( + f"http://127.0.0.1:{self.port}{path}", + method=method, + **kwargs, +) + +return await self.http_client().fetch( + f"http://127.0.0.1:{self.port}{path}", + method=method, + **kwargs, +) + +return ( + await self() + .http_client() + .fetch( + f"http://127.0.0.1:{self.port}{path}", + method=method, + **kwargs, + ) +) + +response = await sync_to_async( + lambda: self.django_handler.get_response(request), thread_sensitive=True +)() +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__starred.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__starred.py.snap index fcc8712509891..2393ae56af7a1 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__starred.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__starred.py.snap @@ -19,6 +19,24 @@ call( [What, i, this, s, very, long, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] ) # trailing value comment ) + +call( + x, + # Leading starred comment + * # Trailing star comment + [ + # Leading value comment + [What, i, this, s, very, long, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + ] # trailing value comment +) + +call( + x, + * # Trailing star comment + ( # Leading value comment + y + ) +) ``` ## Output @@ -42,8 +60,7 @@ call( call( # Leading starred comment - # Leading value comment - *( + *( # Leading value comment [ What, i, @@ -55,6 +72,32 @@ call( ] ) # trailing value comment ) + +call( + x, + # Leading starred comment + # Trailing star comment + *[ + # Leading value comment + [ + What, + i, + this, + s, + very, + long, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + ] + ], # trailing value comment +) + +call( + x, + # Trailing star comment + *( # Leading value comment + y + ), +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap index a3ed8ac6ec4b0..099fbb24a1949 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap @@ -130,6 +130,12 @@ test_particular = [ 'c' ) } + + +# Regression test for https://github.com/astral-sh/ruff/issues/5893 +x = ("""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") +x = (f"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" f"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") +x = (b"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" b"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""") ``` ## Outputs @@ -284,6 +290,21 @@ test_particular = [ # Parenthesized string continuation with messed up indentation {"key": ([], "a" "b" "c")} + + +# Regression test for https://github.com/astral-sh/ruff/issues/5893 +x = ( + """aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" + """bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""" +) +x = ( + f"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" + f"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""" +) +x = ( + b"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" + b"""bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb""" +) ``` @@ -438,6 +459,21 @@ test_particular = [ # Parenthesized string continuation with messed up indentation {'key': ([], 'a' 'b' 'c')} + + +# Regression test for https://github.com/astral-sh/ruff/issues/5893 +x = ( + '''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''' + '''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb''' +) +x = ( + f'''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''' + f'''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb''' +) +x = ( + b'''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''' + b'''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb''' +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__tuple.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__tuple.py.snap index e398db039b0a2..85dfa81fff34f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__tuple.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__tuple.py.snap @@ -9,6 +9,8 @@ a1 = 1, 2 a2 = (1, 2) a3 = (1, 2), 3 a4 = ((1, 2), 3) +a5 = (1), (2) +a6 = ((1), (2)) # Wrapping parentheses checks b1 = (("Michael", "Ende"), ("Der", "satanarchäolügenialkohöllische", "Wunschpunsch"), ("Beelzebub", "Irrwitzer"), ("Tyrannja", "Vamperl"),) @@ -79,6 +81,8 @@ a1 = 1, 2 a2 = (1, 2) a3 = (1, 2), 3 a4 = ((1, 2), 3) +a5 = (1), (2) +a6 = ((1), (2)) # Wrapping parentheses checks b1 = ( @@ -248,14 +252,12 @@ f4 = ( # end-of-line ) # trailing # Comments in other tuples -g1 = ( - # a +g1 = ( # a # b 1, # c # d ) # e -g2 = ( - # a +g2 = ( # a # b 1, # c # d diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__unary.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__unary.py.snap index e0325c897bd0b..b9d8bd127e2c2 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__unary.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__unary.py.snap @@ -146,6 +146,12 @@ if not \ # Regression: https://github.com/astral-sh/ruff/issues/5338 if a and not aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ... + +if ( + not + # comment + a): + ... ``` ## Output @@ -304,6 +310,13 @@ if ( & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ): ... + +if ( + not + # comment + a +): + ... ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__unsplittable.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__unsplittable.py.snap new file mode 100644 index 0000000000000..05f319bf90696 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__unsplittable.py.snap @@ -0,0 +1,173 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/unsplittable.py +--- +## Input +```py +x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +x_aa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +xxxxx = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +while ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + pass + +while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + pass + +# Only applies in `Parenthesize::IfBreaks` positions +raise aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +raise ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) + +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Can never apply on expression statement level +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Is it only relevant for items that can't break + +aaaaaaa = 111111111111111111111111111111111111111111111111111111111111111111111111111111 +aaaaaaa = ( + 1111111111111111111111111111111111111111111111111111111111111111111111111111111 +) + +aaaaaaa = """111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" + +# Never parenthesize multiline strings +aaaaaaa = ( + """1111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" +) + + + +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbb +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + +for converter in connection.ops.get_db_converters( + expression +) + expression.get_db_converters(connection): + ... + + +aaa = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # awkward comment +) + +def test(): + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person, blank=True) + + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyFieldAttributeChainField + +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person, blank=True) +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyFieldAttributeChainFieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeld + +def test(): + if True: + VLM_m2m = VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through + allows_group_by_select_index = self.connection.features.allows_group_by_select_index +``` + +## Output +```py +x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +x_aa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +xxxxx = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) + +while ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + pass + +while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + pass + +# Only applies in `Parenthesize::IfBreaks` positions +raise aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +raise ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) + +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +raise a from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Can never apply on expression statement level +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# Is it only relevant for items that can't break + +aaaaaaa = 111111111111111111111111111111111111111111111111111111111111111111111111111111 +aaaaaaa = ( + 1111111111111111111111111111111111111111111111111111111111111111111111111111111 +) + +aaaaaaa = """111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" + +# Never parenthesize multiline strings +aaaaaaa = """1111111111111111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111111111111111111111111""" + + +aaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbb +aaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) + +aaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) + + +for converter in connection.ops.get_db_converters( + expression +) + expression.get_db_converters(connection): + ... + + +aaa = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # awkward comment + + +def test(): + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = ( + models.ManyToManyField(Person, blank=True) + ) + + m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = ( + models.ManyToManyFieldAttributeChainField + ) + + +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = ( + models.ManyToManyField(Person, blank=True) +) +m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyFieldAttributeChainFieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeld + + +def test(): + if True: + VLM_m2m = ( + VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through + ) + allows_group_by_select_index = ( + self.connection.features.allows_group_by_select_index + ) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap index b5d464ec81c09..7c78a361807a9 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap @@ -63,6 +63,53 @@ def foo(): yield from (yield l) + ( + yield + #comment 1 + * # comment 2 + # comment 3 + test, # comment 4 + 1 + ) + + yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" + ) + + yield aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +yield ("Cache key will cause errors if used with memcached: %r " "(longer than %s)" % ( + key, + MEMCACHE_MAX_KEY_LENGTH, +) + ) + +yield "Cache key will cause errors if used with memcached: %r " "(longer than %s)" % ( + key, + MEMCACHE_MAX_KEY_LENGTH, +) + + +yield ("Unnecessary") + + +yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" +) +yield ( + "# * Remove `managed = False` lines if you wish to allow " + "Django to create, modify, and delete the table" +) +yield ( + "# Feel free to rename the models, but don't rename db_table values or " + "field names." +) + +yield "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " "to the desired behavior" +yield "# * Remove `managed = False` lines if you wish to allow " "Django to create, modify, and delete the table" +yield "# Feel free to rename the models, but don't rename db_table values or " "field names." ``` ## Output @@ -102,7 +149,7 @@ def foo(): for e in l: # comment - yield e # Too many parentheses + yield (e) # Too many parentheses # comment for ridiculouslylongelementnameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee in l: @@ -115,6 +162,74 @@ def foo(): pass yield from (yield l) + + ( + yield ( + # comment 1 + ( + # comment 2 + # comment 3 + *test, # comment 4 + 1, + ) + ) + ) + + yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" + ) + + yield ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + ccccccccccccccccccccccccccccccccccccccccccccccccccccccc + ) + + +yield ( + "Cache key will cause errors if used with memcached: %r " + "(longer than %s)" + % ( + key, + MEMCACHE_MAX_KEY_LENGTH, + ) +) + +yield "Cache key will cause errors if used with memcached: %r " "(longer than %s)" % ( + key, + MEMCACHE_MAX_KEY_LENGTH, +) + + +yield ("Unnecessary") + + +yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" +) +yield ( + "# * Remove `managed = False` lines if you wish to allow " + "Django to create, modify, and delete the table" +) +yield ( + "# Feel free to rename the models, but don't rename db_table values or " + "field names." +) + +yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" +) +yield ( + "# * Remove `managed = False` lines if you wish to allow " + "Django to create, modify, and delete the table" +) +yield ( + "# Feel free to rename the models, but don't rename db_table values or " + "field names." +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__comments.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__comments.py.snap new file mode 100644 index 0000000000000..ad353b6d2f239 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__comments.py.snap @@ -0,0 +1,70 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/comments.py +--- +## Input +```py +pass + +# fmt: off + # A comment that falls into the verbatim range +a + b # a trailing comment + +# in between comments + +# function comment +def test(): + pass + + # under indent + + def nested(): + ... + + # trailing comment that falls into the verbatim range + # trailing outer comment + # fmt: on + +a + b + +def test(): + pass + # fmt: off + # a trailing comment + +``` + +## Output +```py +pass + +# fmt: off + # A comment that falls into the verbatim range +a + b # a trailing comment + +# in between comments + +# function comment +def test(): + pass + + # under indent + + def nested(): + ... + + # trailing comment that falls into the verbatim range + # trailing outer comment + # fmt: on + +a + b + + +def test(): + pass + # fmt: off + # a trailing comment +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__empty_file.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__empty_file.py.snap new file mode 100644 index 0000000000000..7dbe39d5d1abe --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__empty_file.py.snap @@ -0,0 +1,24 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/empty_file.py +--- +## Input +```py +# fmt: off + + # this does not work because there are no statements + +# fmt: on +``` + +## Output +```py +# fmt: off + +# this does not work because there are no statements + +# fmt: on +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_docstring.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_docstring.py.snap new file mode 100644 index 0000000000000..dd1d9c6714226 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_docstring.py.snap @@ -0,0 +1,91 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_docstring.py +--- +## Input +```py +def test(): + # fmt: off + """ This docstring does not + get formatted + """ + + # fmt: on + + but + this + does + +def test(): + # fmt: off + # just for fun + # fmt: on + # leading comment + """ This docstring gets formatted + """ # trailing comment + + and_this + gets + formatted + too +``` + +## Outputs +### Output 1 +``` +indent-style = Spaces, size: 4 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + """ This docstring does not + get formatted + """ + + # fmt: on + + but + this + does + + +def test(): + # fmt: off + # just for fun + # fmt: on + # leading comment + """This docstring gets formatted""" # trailing comment + + and_this + gets + formatted + too +``` + + +### Output 2 +``` +indent-style = Spaces, size: 2 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + """ This docstring does not + get formatted + """ + + # fmt: on + + but + this + does + + +def test(): + # fmt: off + # just for fun + # fmt: on + # leading comment + """This docstring gets formatted""" # trailing comment + + and_this + gets + formatted + too +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__form_feed.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__form_feed.py.snap new file mode 100644 index 0000000000000..0c009fa42416d --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__form_feed.py.snap @@ -0,0 +1,28 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/form_feed.py +--- +## Input +```py +# fmt: off +# DB layer (form feed at the start of the next line) + +# fmt: on + +def test(): + pass +``` + +## Output +```py +# fmt: off +# DB layer (form feed at the start of the next line) + +# fmt: on + +def test(): + pass +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__indent.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__indent.py.snap new file mode 100644 index 0000000000000..37ea15222f49b --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__indent.py.snap @@ -0,0 +1,272 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.py +--- +## Input +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + pass + more + # fmt: on + + formatted + + def test(): + a_small_indent + # fmt: off +# fix under-indented comments + (or_the_inner_expression + +expressions + ) + + if True: + pass + # fmt: on + + +# fmt: off +def test(): + pass + + # It is necessary to indent comments because the following fmt: on comment because it otherwise becomes a trailing comment + # of the `test` function if the "proper" indentation is larger than 2 spaces. + # fmt: on + +disabled + formatting; + +# fmt: on + +formatted; + +def test(): + pass + # fmt: off + """A multiline strings + that should not get formatted""" + + "A single quoted multiline \ + string" + + disabled + formatting; + +# fmt: on + +formatted; +``` + +## Outputs +### Output 1 +``` +indent-style = Spaces, size: 4 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + pass + more + # fmt: on + + formatted + + def test(): + a_small_indent + # fmt: off + # fix under-indented comments + (or_the_inner_expression + +expressions + ) + + if True: + pass + # fmt: on + + +# fmt: off +def test(): + pass + + # It is necessary to indent comments because the following fmt: on comment because it otherwise becomes a trailing comment + # of the `test` function if the "proper" indentation is larger than 2 spaces. + # fmt: on + +disabled + formatting; + +# fmt: on + +formatted + + +def test(): + pass + # fmt: off + """A multiline strings + that should not get formatted""" + + "A single quoted multiline \ + string" + + disabled + formatting + + +# fmt: on + +formatted +``` + + +### Output 2 +``` +indent-style = Spaces, size: 1 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + pass + more + # fmt: on + + formatted + + def test(): + a_small_indent + # fmt: off + # fix under-indented comments + (or_the_inner_expression + +expressions + ) + + if True: + pass + # fmt: on + + +# fmt: off +def test(): + pass + + # It is necessary to indent comments because the following fmt: on comment because it otherwise becomes a trailing comment + # of the `test` function if the "proper" indentation is larger than 2 spaces. + # fmt: on + +disabled + formatting; + +# fmt: on + +formatted + + +def test(): + pass + # fmt: off + """A multiline strings + that should not get formatted""" + + "A single quoted multiline \ + string" + + disabled + formatting + + +# fmt: on + +formatted +``` + + +### Output 3 +``` +indent-style = Tab +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + pass + more + # fmt: on + + formatted + + def test(): + a_small_indent + # fmt: off + # fix under-indented comments + (or_the_inner_expression + +expressions + ) + + if True: + pass + # fmt: on + + +# fmt: off +def test(): + pass + + # It is necessary to indent comments because the following fmt: on comment because it otherwise becomes a trailing comment + # of the `test` function if the "proper" indentation is larger than 2 spaces. + # fmt: on + +disabled + formatting; + +# fmt: on + +formatted + + +def test(): + pass + # fmt: off + """A multiline strings + that should not get formatted""" + + "A single quoted multiline \ + string" + + disabled + formatting + + +# fmt: on + +formatted +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__last_statement.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__last_statement.py.snap new file mode 100644 index 0000000000000..07d0eeaf0c52c --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__last_statement.py.snap @@ -0,0 +1,35 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/last_statement.py +--- +## Input +```py +def test(): + # fmt: off + + a + b + + + + # suppressed comments + +a + b # formatted +``` + +## Output +```py +def test(): + # fmt: off + + a + b + + + + # suppressed comments + + +a + b # formatted +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__mixed_space_and_tab.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__mixed_space_and_tab.py.snap new file mode 100644 index 0000000000000..1027b24e41ecb --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__mixed_space_and_tab.py.snap @@ -0,0 +1,103 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/mixed_space_and_tab.py +--- +## Input +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: +# Fun tab, space, tab, space. Followed by space, tab, tab, space + pass + more + else: + other + # fmt: on + +``` + +## Outputs +### Output 1 +``` +indent-style = Spaces, size: 4 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + # Fun tab, space, tab, space. Followed by space, tab, tab, space + pass + more + else: + other +# fmt: on +``` + + +### Output 2 +``` +indent-style = Spaces, size: 2 +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + # Fun tab, space, tab, space. Followed by space, tab, tab, space + pass + more + else: + other +# fmt: on +``` + + +### Output 3 +``` +indent-style = Tab +line-width = 88 +quote-style = Double +magic-trailing-comma = Respect +``` + +```py +def test(): + # fmt: off + a_very_small_indent + ( +not_fixed + ) + + if True: + # Fun tab, space, tab, space. Followed by space, tab, tab, space + pass + more + else: + other +# fmt: on +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__no_fmt_on.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__no_fmt_on.py.snap new file mode 100644 index 0000000000000..15ded04ff663c --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__no_fmt_on.py.snap @@ -0,0 +1,33 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/no_fmt_on.py +--- +## Input +```py +def test(): + # fmt: off + not formatted + + if unformatted + a: + pass + +# Get's formatted again +a + b +``` + +## Output +```py +def test(): + # fmt: off + not formatted + + if unformatted + a: + pass + + +# Get's formatted again +a + b +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__off_on_off_on.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__off_on_off_on.py.snap new file mode 100644 index 0000000000000..c33f5faa9b76a --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__off_on_off_on.py.snap @@ -0,0 +1,156 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/off_on_off_on.py +--- +## Input +```py +# Tricky sequences of fmt off and on + +# Formatted +a + b + +# fmt: off + # not formatted 1 +# fmt: on +a + b + # formatted + + +# fmt: off + # not formatted 1 +# fmt: on + # not formatted 2 +# fmt: off +a + b +# fmt: on + + +# fmt: off + # not formatted 1 +# fmt: on + # formatted 1 +# fmt: off + # not formatted 2 +a + b +# fmt: on + # formatted +b + c + + +# fmt: off +a + b + + # not formatted +# fmt: on + # formatted +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on + # formatted +# fmt: off + # not formatted 2 +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on + # formatted + +# leading +a + b +# fmt: off + + # leading unformatted +def test (): + pass + + # fmt: on + +a + b +``` + +## Output +```py +# Tricky sequences of fmt off and on + +# Formatted +a + b + +# fmt: off + # not formatted 1 +# fmt: on +a + b +# formatted + + +# fmt: off + # not formatted 1 +# fmt: on +# not formatted 2 +# fmt: off +a + b +# fmt: on + + +# fmt: off + # not formatted 1 +# fmt: on +# formatted 1 +# fmt: off + # not formatted 2 +a + b +# fmt: on +# formatted +b + c + + +# fmt: off +a + b + + # not formatted +# fmt: on +# formatted +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on +# formatted +# fmt: off + # not formatted 2 +a + b + + +# fmt: off +a + b + + # not formatted 1 +# fmt: on +# formatted + +# leading +a + b +# fmt: off + + # leading unformatted +def test (): + pass + + # fmt: on + +a + b +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__simple.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__simple.py.snap new file mode 100644 index 0000000000000..e9f968a425075 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__simple.py.snap @@ -0,0 +1,32 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/simple.py +--- +## Input +```py +# Get's formatted +a + b + +# fmt: off +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b +``` + +## Output +```py +# Get's formatted +a + b + +# fmt: off +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__trailing_comments.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__trailing_comments.py.snap new file mode 100644 index 0000000000000..e80951bd3ac25 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__trailing_comments.py.snap @@ -0,0 +1,96 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/trailing_comments.py +--- +## Input +```py +a = 10 +# fmt: off + +# more format + +def test(): ... + + +# fmt: on + +b = 20 +# Sequence of trailing comments that toggle between format on and off. The sequence ends with a `fmt: on`, so that the function gets formatted. +# formatted 1 +# fmt: off + # not formatted +# fmt: on + # formatted comment +# fmt: off + # not formatted 2 +# fmt: on + + # formatted +def test2 (): + ... + +a = 10 + +# Sequence of trailing comments that toggles between format on and off. The sequence ends with a `fmt: off`, so that the function is not formatted. + # formatted 1 +# fmt: off + # not formatted +# fmt: on + # formattd +# fmt: off + + # not formatted +def test3 (): + ... + +# fmt: on +``` + +## Output +```py +a = 10 +# fmt: off + +# more format + +def test(): ... + + +# fmt: on + +b = 20 +# Sequence of trailing comments that toggle between format on and off. The sequence ends with a `fmt: on`, so that the function gets formatted. +# formatted 1 +# fmt: off + # not formatted +# fmt: on +# formatted comment +# fmt: off + # not formatted 2 +# fmt: on + + +# formatted +def test2(): + ... + + +a = 10 + +# Sequence of trailing comments that toggles between format on and off. The sequence ends with a `fmt: off`, so that the function is not formatted. +# formatted 1 +# fmt: off + # not formatted +# fmt: on +# formattd +# fmt: off + + # not formatted +def test3 (): + ... + +# fmt: on +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__yapf.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__yapf.py.snap new file mode 100644 index 0000000000000..45f0ad07d0ea0 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__yapf.py.snap @@ -0,0 +1,48 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/yapf.py +--- +## Input +```py +# Get's formatted +a + b + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# yapf: enable + +# Get's formatted again +a + b + + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b +``` + +## Output +```py +# Get's formatted +a + b + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# yapf: enable + +# Get's formatted again +a + b + + +# yapf: disable +a + [1, 2, 3, 4, 5 ] +# fmt: on + +# Get's formatted again +a + b +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__decorators.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__decorators.py.snap new file mode 100644 index 0000000000000..330e73752d3f2 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__decorators.py.snap @@ -0,0 +1,49 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/decorators.py +--- +## Input +```py + +@FormattedDecorator(a =b) + # leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip + # leading class comment +class Test: + pass + + + +@FormattedDecorator(a =b) +# leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip +# leading class comment +def test(): + pass + +``` + +## Output +```py +@FormattedDecorator(a=b) +# leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip +# leading class comment +class Test: + pass + + +@FormattedDecorator(a=b) +# leading comment +@MyDecorator( # dangling comment + list = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12], x = some_other_function_call({ "test": "value", "more": "other"})) # fmt: skip +# leading class comment +def test(): + pass +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__docstrings.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__docstrings.py.snap new file mode 100644 index 0000000000000..ffb045fff81b5 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__docstrings.py.snap @@ -0,0 +1,40 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/docstrings.py +--- +## Input +```py +def test(): + # leading comment + """ This docstring does not + get formatted + """ # fmt: skip + # trailing comment + +def test(): + # leading comment + """ This docstring gets formatted + """ # trailing comment + + and_this + gets + formatted + too +``` + +## Output +```py +def test(): + # leading comment + """ This docstring does not + get formatted + """ # fmt: skip + # trailing comment + + +def test(): + # leading comment + """This docstring gets formatted""" # trailing comment + + and_this + gets + formatted + too +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap new file mode 100644 index 0000000000000..32daa63f6652d --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap @@ -0,0 +1,166 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/match.py +--- +## Input +```py +def http_error(status): + match status : # fmt: skip + case 400 : # fmt: skip + return "Bad request" + case 404: + return "Not found" + case 418: + return "I'm a teapot" + case _: + return "Something's wrong with the internet" + +# point is an (x, y) tuple +match point: + case (0, 0): # fmt: skip + print("Origin") + case (0, y): + print(f"Y={y}") + case (x, 0): + print(f"X={x}") + case (x, y): + print(f"X={x}, Y={y}") + case _: + raise ValueError("Not a point") + +class Point: + x: int + y: int + +def location(point): + match point: + case Point(x=0, y =0 ) : # fmt: skip + print("Origin is the point's location.") + case Point(x=0, y=y): + print(f"Y={y} and the point is on the y-axis.") + case Point(x=x, y=0): + print(f"X={x} and the point is on the x-axis.") + case Point(): + print("The point is located somewhere else on the plane.") + case _: + print("Not a point") + + +match points: + case []: + print("No points in the list.") + case [ + Point(0, 0) + ]: # fmt: skip + print("The origin is the only point in the list.") + case [Point(x, y)]: + print(f"A single point {x}, {y} is in the list.") + case [Point(0, y1), Point(0, y2)]: + print(f"Two points on the Y axis at {y1}, {y2} are in the list.") + case _: + print("Something else is found in the list.") + + +match test_variable: + case ( + 'warning', + code, + 40 + ): # fmt: skip + print("A warning has been received.") + case ('error', code, _): + print(f"An error {code} occurred.") + + +match point: + case Point(x, y) if x == y: # fmt: skip + print(f"The point is located on the diagonal Y=X at {x}.") + case Point(x, y): + print(f"Point is not on the diagonal.") +``` + +## Output +```py +def http_error(status): + match status : # fmt: skip + case 400 : # fmt: skip + return "Bad request" + case 404: + return "Not found" + case 418: + return "I'm a teapot" + case _: + return "Something's wrong with the internet" + + +# point is an (x, y) tuple +match point: + case (0, 0): # fmt: skip + print("Origin") + case (0, y): + print(f"Y={y}") + case (x, 0): + print(f"X={x}") + case (x, y): + print(f"X={x}, Y={y}") + case _: + raise ValueError("Not a point") + + +class Point: + x: int + y: int + + +def location(point): + match point: + case Point(x=0, y =0 ) : # fmt: skip + print("Origin is the point's location.") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"Y={y} and the point is on the y-axis.") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"X={x} and the point is on the x-axis.") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print("The point is located somewhere else on the plane.") + case _: + print("Not a point") + + +match points: + case []: + print("No points in the list.") + case [ + Point(0, 0) + ]: # fmt: skip + print("The origin is the only point in the list.") + case [NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0)]: + print(f"A single point {x}, {y} is in the list.") + case [ + NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0), + NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0), + ]: + print(f"Two points on the Y axis at {y1}, {y2} are in the list.") + case _: + print("Something else is found in the list.") + + +match test_variable: + case ( + 'warning', + code, + 40 + ): # fmt: skip + print("A warning has been received.") + case ("error", code, _): + print(f"An error {code} occurred.") + + +match point: + case Point(x, y) if x == y: # fmt: skip + print(f"The point is located on the diagonal Y=X at {x}.") + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): + print(f"Point is not on the diagonal.") +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__or_else.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__or_else.py.snap new file mode 100644 index 0000000000000..4293169e6bb0b --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__or_else.py.snap @@ -0,0 +1,76 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/or_else.py +--- +## Input +```py +for item in container: + if search_something(item): + # Found it! + process(item) + break + # leading comment +else : #fmt: skip + # Didn't find anything.. + not_found_in_container() + + +while i < 10: + print(i) + +# leading comment +else : #fmt: skip + # Didn't find anything.. + print("I was already larger than 9") + + +try : # fmt: skip + some_call() +except Exception : # fmt: skip + pass +except : # fmt: skip + handle_exception() + +else : # fmt: skip + pass +finally : # fmt: skip + finally_call() +``` + +## Output +```py +for item in container: + if search_something(item): + # Found it! + process(item) + break +# leading comment +else : # fmt: skip + # Didn't find anything.. + not_found_in_container() + + +while i < 10: + print(i) + +# leading comment +else : # fmt: skip + # Didn't find anything.. + print("I was already larger than 9") + + +try : # fmt: skip + some_call() +except Exception : # fmt: skip + pass +except : # fmt: skip + handle_exception() + +else : # fmt: skip + pass +finally : # fmt: skip + finally_call() +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__parentheses.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__parentheses.py.snap new file mode 100644 index 0000000000000..30d4872aed1a5 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__parentheses.py.snap @@ -0,0 +1,54 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/parentheses.py +--- +## Input +```py +if ( + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 # trailing condition comment + # trailing own line comment +): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and ((((y)))): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and y: # fmt: skip + pass +``` + +## Output +```py +if ( + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 # trailing condition comment + # trailing own line comment +): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and ((((y)))): # fmt: skip + pass + + +if ( # trailing open parentheses comment + # a leading condition comment + len([1, 23, 3, 4, 5]) > 2 +) and y: # fmt: skip + pass +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__type_params.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__type_params.py.snap new file mode 100644 index 0000000000000..9bc2f32e01ccd --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__type_params.py.snap @@ -0,0 +1,94 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_skip/type_params.py +--- +## Input +```py +class TestTypeParam[ T ]: # fmt: skip + pass + +class TestTypeParam [ # trailing open paren comment + # leading comment + T # trailing type param comment + # trailing type param own line comment +]: # fmt: skip + pass + +class TestTrailingComment4[ + T +] ( # trailing arguments open parenthesis comment + # leading argument comment + A # trailing argument comment + # trailing argument own line comment +): # fmt: skip + pass + +def test [ + # comment + A, + + # another + + B, +] (): # fmt: skip + ... + +def test [ + # comment + A, + + # another + + B, +] () -> str: # fmt: skip + ... +``` + +## Output +```py +class TestTypeParam[ T ]: # fmt: skip + pass + + +class TestTypeParam [ # trailing open paren comment + # leading comment + T # trailing type param comment + # trailing type param own line comment +]: # fmt: skip + pass + + +class TestTrailingComment4[ + T +] ( # trailing arguments open parenthesis comment + # leading argument comment + A # trailing argument comment + # trailing argument own line comment +): # fmt: skip + pass + + +def test [ + # comment + A, + + # another + + B, +] (): # fmt: skip + ... + + +def test [ + # comment + A, + + # another + + B, +] () -> str: # fmt: skip + ... +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__call_chains.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__call_chains.py.snap new file mode 100644 index 0000000000000..8c8c952a79d7f --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__call_chains.py.snap @@ -0,0 +1,354 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/call_chains.py +--- +## Input +```py +# Test cases for call chains and optional parentheses, with and without fluent style + +raise OsError("") from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a(aaaa) + +raise OsError( + "sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll" +) from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a( + aaaa +) + +a1 = Blog.objects.filter(entry__headline__contains="Lennon").filter( + entry__pub_date__year=2008 +) + +a2 = Blog.objects.filter( + entry__headline__contains="Lennon", +).filter( + entry__pub_date__year=2008, +) + +raise OsError("") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +raise OsError("sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +# Break only after calls and indexing +b1 = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ) + .count() +) + +b2 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .limit_results[:10] + .filter( + entry__pub_date__month=10, + ) +) + +# Nested call chains +c1 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ).filter( + entry__pub_date__year=2008, + ) + + Blog.objects.filter( + entry__headline__contains="McCartney", + ) + .limit_results[:10] + .filter( + entry__pub_date__year=2010, + ) +).all() + +# Test different cases with trailing end of line comments: +# * fluent style, fits: no parentheses -> ignore the expand_parent +# * fluent style, doesn't fit: break all soft line breaks +# * default, fits: no parentheses +# * default, doesn't fit: parentheses but no soft line breaks + +# Fits, either style +d11 = x.e().e().e() # +d12 = (x.e().e().e()) # +d13 = ( + x.e() # + .e() + .e() +) + +# Doesn't fit, default +d2 = ( + x.e().esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdddd() # +) + +# Doesn't fit, fluent style +d3 = ( + x.e() # + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() +) + +# Don't drop the bin op parentheses +e1 = (1 + 2).w().t() +e2 = (1 + 2)().w().t() +e3 = (1 + 2)[1].w().t() + +# Treat preserved parentheses correctly +f1 = (b().c()).d(1,) +f2 = b().c().d(1,) +f3 = (b).c().d(1,) +f4 = (a)(b).c(1,) +f5 = (a.b()).c(1,) + +# Indent in the parentheses without breaking +g1 = ( + queryset.distinct().order_by(field.name).values_list(field_name_flat_long_long=True) +) + +# Fluent style in subexpressions +if ( + not a() + .b() + .cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc() +): + pass +h2 = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + ccccccccccccccccccccccccc() + .dddddddddddddddddddddd() + .eeeeeeeeee() + .ffffffffffffffffffffff() +) + +# Parentheses aren't allowed on statement level, don't use fluent style here +if True: + (alias).filter(content_typeold_content_type).update( + content_typenew_contesadfasfdant_type + ) + +zero( + one, +).two( + three, +).four( + five, +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id() +) +``` + +## Output +```py +# Test cases for call chains and optional parentheses, with and without fluent style + +raise OsError("") from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a(aaaa) + +raise OsError( + "sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll" +) from a.aaaaa( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +).a(aaaa) + +a1 = Blog.objects.filter(entry__headline__contains="Lennon").filter( + entry__pub_date__year=2008 +) + +a2 = Blog.objects.filter( + entry__headline__contains="Lennon", +).filter( + entry__pub_date__year=2008, +) + +raise OsError("") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +raise OsError("sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll") from ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .filter( + entry__pub_date__year=2008, + ) + .filter( + entry__pub_date__year=2008, + ) +) + +# Break only after calls and indexing +b1 = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ) + .count() +) + +b2 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ) + .limit_results[:10] + .filter( + entry__pub_date__month=10, + ) +) + +# Nested call chains +c1 = ( + Blog.objects.filter( + entry__headline__contains="Lennon", + ).filter( + entry__pub_date__year=2008, + ) + + Blog.objects.filter( + entry__headline__contains="McCartney", + ) + .limit_results[:10] + .filter( + entry__pub_date__year=2010, + ) +).all() + +# Test different cases with trailing end of line comments: +# * fluent style, fits: no parentheses -> ignore the expand_parent +# * fluent style, doesn't fit: break all soft line breaks +# * default, fits: no parentheses +# * default, doesn't fit: parentheses but no soft line breaks + +# Fits, either style +d11 = x.e().e().e() # +d12 = x.e().e().e() # +d13 = ( + x.e() # + .e() + .e() +) + +# Doesn't fit, default +d2 = x.e().esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdddd() # + +# Doesn't fit, fluent style +d3 = ( + x.e() # + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() + .esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk() +) + +# Don't drop the bin op parentheses +e1 = (1 + 2).w().t() +e2 = (1 + 2)().w().t() +e3 = (1 + 2)[1].w().t() + +# Treat preserved parentheses correctly +f1 = (b().c()).d( + 1, +) +f2 = ( + b() + .c() + .d( + 1, + ) +) +f3 = ( + (b) + .c() + .d( + 1, + ) +) +f4 = (a)(b).c( + 1, +) +f5 = (a.b()).c( + 1, +) + +# Indent in the parentheses without breaking +g1 = ( + queryset.distinct().order_by(field.name).values_list(field_name_flat_long_long=True) +) + +# Fluent style in subexpressions +if ( + not a() + .b() + .cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc() +): + pass +h2 = ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + ccccccccccccccccccccccccc() + .dddddddddddddddddddddd() + .eeeeeeeeee() + .ffffffffffffffffffffff() +) + +# Parentheses aren't allowed on statement level, don't use fluent style here +if True: + (alias).filter(content_typeold_content_type).update( + content_typenew_contesadfasfdant_type + ) + +zero( + one, +).two( + three, +).four( + five, +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id +) + +max_message_id = ( + Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id() +) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__nested.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__nested.py.snap new file mode 100644 index 0000000000000..2106ed7f658e2 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__nested.py.snap @@ -0,0 +1,139 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/nested.py +--- +## Input +```py +a1 = f( # 1 + g( # 2 + ) +) +a2 = f( # 1 + g( # 2 + x + ) +) +a3 = f( + ( + # + () + ) +) + + +call( + a, + b, + [ # Empty because of + ] +) + +a = a + b + c + d + ( # Hello + e + f + g +) + +a = int( # type: ignore + int( # type: ignore + int( # type: ignore + 6 + ) + ) +) + +# Stability and correctness checks +b1 = () - ( # +) +() - ( # +) +b2 = () - f( # +) +() - f( # +) +b3 = ( + # + () +) +( + # + () +) +``` + +## Output +```py +a1 = f( # 1 + g( # 2 + ) +) +a2 = f( # 1 + g( # 2 + x + ) +) +a3 = f( + ( + # + () + ) +) + + +call( + a, + b, + [ # Empty because of + ], +) + +a = ( + a + + b + + c + + d + + + ( # Hello + e + f + g + ) +) + +a = int( # type: ignore + int( # type: ignore + int( # type: ignore + 6 + ) + ) +) + +# Stability and correctness checks +b1 = ( + () + - ( # + ) +) +( + () + - ( # + ) +) +b2 = ( + () + - f( # + ) +) +( + () + - f( # + ) +) +b3 = ( + # + () +) +( + # + () +) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap new file mode 100644 index 0000000000000..7f619ec37fa1f --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap @@ -0,0 +1,193 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_empty.py +--- +## Input +```py +# Opening parentheses end-of-line comment without a value in the parentheses + +( # a 1 +) +a2 = ( # a 2 +) +a3 = f( # a 3 +) +a4 = ( # a 4 +) = a4 +a5: List( # a 5 +) = 5 + +raise ( # b 1a +) +raise b1b from ( # b 1b +) +raise ( # b 1c +) from b1c +del ( # b 2 +) +assert ( # b 3 +), ( #b 4 +) + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + ) + yield ( # c 2 + ) +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + ) + +with ( # d 1 +): pass +match ( # d 2 +): + case d2: + pass +match d3: + case ( # d 3 + ): + pass +while ( # d 4 +): + pass +if ( # d 5 +): + pass +elif ( # d 6 +): + pass +for ( # d 7 +) in ( # d 8 +): + pass +try: + pass +except ( # d 9 +): + pass + + +def e1( # e 1 +): pass + + +def e2() -> ( # e 2 +): pass + + +class E3( # e 3 +): pass + + +f1 = [ # f 1 +] +[ # f 2 +] +f3 = { # f3 +} +{ # f 4 +} +``` + +## Output +```py +# Opening parentheses end-of-line comment without a value in the parentheses + +( # a 1 +) +a2 = ( # a 2 +) +a3 = f( # a 3 +) +a4 = ( # a 4 +) = a4 +a5: List( # a 5 +) = 5 + +raise ( # b 1a +) +raise b1b from ( # b 1b +) +raise ( # b 1c +) from b1c +del ( # b 2 +) +assert ( # b 3 +), ( # b 4 +) + + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + ) + yield ( # c 2 + ) + + +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + ) + + +with ( # d 1 +): + pass +match ( # d 2 +): + case d2: + pass +match d3: + case ( # d 3 + ): + pass +while ( # d 4 +): + pass +if ( # d 5 +): + pass +elif ( # d 6 +): + pass +for ( # d 7 +) in ( # d 8 +): + pass +try: + pass +except ( # d 9 +): + pass + + +def e1( # e 1 +): + pass + + +def e2() -> ( # e 2 +): + pass + + +class E3: # e 3 + pass + + +f1 = [ # f 1 +] +[ # f 2 +] +f3 = { # f3 +} +{ # f 4 +} +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap new file mode 100644 index 0000000000000..0c287d1b0ba89 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap @@ -0,0 +1,349 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/parentheses/opening_parentheses_comment_value.py +--- +## Input +```py +# Opening parentheses end-of-line comment with value in the parentheses + +( # a 1 +x) +a2 = ( # a 2 +x) +a3 = f( # a 3 +x) +a4 = ( # a 4 +x) = a4 +a5: List( # a 5 +x) = 5 + +raise ( # b 1a +x) +raise b1b from ( # b 1b +x) +raise ( # b 1c +x) from b1c +del ( # b 2 +x) +assert ( # b 3 +x), ( #b 4 +x) + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + x) + yield ( # c 2 + x) +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + x) + +with ( # d 1 +x): pass +match ( # d 2 +x): + case d2: + pass +match d3: + case ( # d 3 + x): + pass +while ( # d 4 +x): + pass +if ( # d 5 +x): + pass +elif ( # d 6 +y): + pass +for ( # d 7 +x) in ( # d 8 +y): + pass +try: + pass +except ( # d 9 + x +): + pass + + +def e1( # e 1 +x): pass + + +def e2() -> ( # e 2 +x): pass + + +def e3() -> ( + # e 2 +x): pass + + +def e4() -> ( + x +# e 4 +): pass + + +def e5() -> ( # e 5 + ( # e 5 + x + ) +): pass + + +def e6() -> ( + ( + # e 6 + x + ) +): pass + + +def e7() -> ( + ( + x + # e 7 + ) +): pass + + +def e8() -> ( + ( + x + ) + # e 8 +): pass + + +class E9( # e 9 +x): pass + + +f1 = [ # f 1 +x] +[ # f 2 +x] +f3 = { # f3 +x} +{ # f 4 +x} + + + +# Non-empty parentheses: These are not allowed without a value +def f1[ # f1 + T +](): pass +f2 = ( # f2 + i for i in range(10) +) +f3 = [ # f3 + i for i in range(10) +] +f4 = { # f4 + i for i in range(10) +} +f5 = { # f5 + i: i**2 for i in range(10) +} + + +``` + +## Output +```py +# Opening parentheses end-of-line comment with value in the parentheses + +( # a 1 + x +) +a2 = ( # a 2 + x +) +a3 = f( # a 3 + x +) +a4 = ( # a 4 + x +) = a4 +a5: List( # a 5 + x +) = 5 + +raise ( # b 1a + x +) +raise b1b from ( # b 1b + x +) +raise ( # b 1c + x +) from b1c +del ( # b 2 + x +) +assert ( # b 3 + x +), ( # b 4 + x +) + + +def g(): + """Statements that are only allowed in function bodies""" + return ( # c 1 + x + ) + yield ( # c 2 + x + ) + + +async def h(): + """Statements that are only allowed in async function bodies""" + await ( # c 3 + x + ) + + +with ( # d 1 + x +): + pass +match ( # d 2 + x +): + case d2: + pass +match d3: + case ( # d 3 + x + ): + pass +while ( # d 4 + x +): + pass +if ( # d 5 + x +): + pass +elif ( # d 6 + y +): + pass +for ( # d 7 + x +) in ( # d 8 + y +): + pass +try: + pass +except ( # d 9 + x +): + pass + + +def e1( # e 1 + x +): + pass + + +def e2() -> ( # e 2 + x +): + pass + + +def e3() -> ( + # e 2 + x +): + pass + + +def e4() -> ( + x + # e 4 +): + pass + + +def e5() -> ( # e 5 + # e 5 + x +): + pass + + +def e6() -> ( + # e 6 + x +): + pass + + +def e7() -> ( + x + # e 7 +): + pass + + +def e8() -> ( + x + # e 8 +): + pass + + +class E9( # e 9 + x +): + pass + + +f1 = [ # f 1 + x +] +[ # f 2 + x +] +f3 = { # f3 + x +} +{ # f 4 + x +} + + +# Non-empty parentheses: These are not allowed without a value +def f1[T](): # f1 + pass + + +f2 = ( # f2 + i for i in range(10) +) +f3 = [ # f3 + i for i in range(10) +] +f4 = { # f4 + i for i in range(10) +} +f5 = { # f5 + i: i**2 for i in range(10) +} +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@skip_magic_trailing_comma.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@skip_magic_trailing_comma.py.snap index f0beff4915d25..a799ac9bc6c99 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@skip_magic_trailing_comma.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@skip_magic_trailing_comma.py.snap @@ -33,6 +33,10 @@ def g(a,): pass x1 = lambda y: 1 x2 = lambda y,: 1 + +# Ignore trailing comma. +with (a,): # magic trailing comma + ... ``` ## Outputs @@ -78,6 +82,12 @@ def g( x1 = lambda y: 1 x2 = lambda y,: 1 + +# Ignore trailing comma. +with ( + a, +): # magic trailing comma + ... ``` @@ -117,6 +127,10 @@ def g(a): x1 = lambda y: 1 x2 = lambda y,: 1 + +# Ignore trailing comma. +with a: # magic trailing comma + ... ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__assert.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__assert.py.snap index 089244c385f89..2db923a1dfbe6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__assert.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__assert.py.snap @@ -18,7 +18,7 @@ assert ( # Dangle1 assert ( # Leading test value True # Trailing test value same-line - # Trailing test value own-line + # Trailing test value own-line ), "Some string" # Trailing msg same-line # Trailing assert @@ -29,11 +29,136 @@ assert ( assert ( # Leading test value True # Trailing test value same-line - # Trailing test value own-line + # Trailing test value own-line # Test dangler ), "Some string" # Trailing msg same-line # Trailing assert + +def test(): + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, ( + "Not what we expected and the message is too long to fit ineeeeee one line" + ) + + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, ( + "Not what we expected and the message is too long to fit in one lineeeee" + ) + + assert { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } == expected, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee" + + assert expected == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + }, "Not what we expected and the message is too long to fit ineeeeee one line" + + assert expected == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + }, "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee" ``` ## Output @@ -52,10 +177,8 @@ assert ( # Dangle1 assert ( # Leading test value True # Trailing test value same-line -), ( # Trailing test value own-line - "Some string" -) # Trailing msg same-line +), "Some string" # Trailing msg same-line # Trailing assert # Random dangler @@ -65,12 +188,145 @@ assert ( assert ( # Leading test value True # Trailing test value same-line -), ( # Trailing test value own-line # Test dangler - "Some string" -) # Trailing msg same-line +), "Some string" # Trailing msg same-line + + # Trailing assert + +def test(): + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expected + ), "Not what we expected and the message is too long to fit ineeeeee one line" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expected + ), "Not what we expected and the message is too long to fit in one lineeeee" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expected + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + == expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee" + + assert expected == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + }, "Not what we expected and the message is too long to fit ineeeeee one line" + + assert ( + expected + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lin" + + assert ( + expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + == { + key1: value1, + key2: value2, + key3: value3, + key4: value4, + key5: value5, + key6: value6, + key7: value7, + key8: value8, + key9: value9, + } + ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee" ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__assign.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__assign.py.snap index 4134d2b91e586..03b8bf6fec107 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__assign.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__assign.py.snap @@ -19,9 +19,47 @@ aa = [ bakjdshflkjahdslkfjlasfdahjlfds ] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] +aa = [ + +] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = [ + # foo +] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = ([ +]) = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + aaaa = ( # trailing # comment bbbbb) = cccccccccccccccc = 3 + +x = ( # comment + [ # comment + a, + b, + c, + ] +) = 1 + + +x = ( + # comment + [ + a, + b, + c, + ] +) = 1 + + +x = ( + [ # comment + a, + b, + c, + ] +) = 1 ``` ## Output @@ -47,10 +85,43 @@ aa = [ bakjdshflkjahdslkfjlasfdahjlfds ] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] +aa = [] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = [ + # foo +] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + +aa = [] = dddd = ddd = fkjaödkjaföjfahlfdalfhaöfaöfhaöfha = g = [3] + aaaa = ( # trailing # comment bbbbb ) = cccccccccccccccc = 3 + +x = ( # comment + [ # comment + a, + b, + c, + ] +) = 1 + + +x = ( + # comment + [ + a, + b, + c, + ] +) = 1 + + +x = [ # comment + a, + b, + c, +] = 1 ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__class_definition.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__class_definition.py.snap index 894f2b96e86b5..185579f0799a0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__class_definition.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__class_definition.py.snap @@ -49,6 +49,169 @@ class TestTrailingComment2: # trailing comment pass +class TestTrailingComment3[T]: # trailing comment + pass + + +class TestTrailingComment4[T](A): # trailing comment + pass + + +class Test: + """Docstring""" + + +class Test: + # comment + """Docstring""" + + +class Test: + """Docstring""" + x = 1 + + +class Test: + """Docstring""" + # comment + x = 1 + + +class Test: + + """Docstring""" + + +class Test: + # comment + + """Docstring""" + + +class Test: + + # comment + + """Docstring""" + + +class Test: + + """Docstring""" + x = 1 + + +class Test: + + """Docstring""" + # comment + x = 1 + + +class C(): # comment + pass + + +class C( # comment +): + pass + + +class C( + # comment +): + pass + + +class C(): # comment + pass + + +class C( # comment + # comment + 1 +): + pass + + +class C( + 1 + # comment +): + pass + + +@dataclass +# Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +class AltCLIPOutput(ModelOutput): + ... + + +@dataclass +class AltCLIPOutput( # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +): + ... + + +@dataclass +class AltCLIPOutput( + # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +): + ... + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, Cccccccccccccccccccccc]: + pass + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, *Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, **Cccccccccccccccccccccc]: + pass + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[*Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[**Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: + pass + + +class TestTypeParams[**P, *Ts, T]: + pass + + +class TestTypeParams[ # trailing bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +]: + pass + + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](B, C, D): + pass + + + +class TestTypeParams[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, Cccccccccccccccccccccccc, Ddddddddddddddddddddddddd): + pass + + + +class TestTypeParams[A, B, C](meta=Aaaaaaaaaaaaaaaaaaaaaa): + pass ``` ## Output @@ -67,8 +230,7 @@ class Test((Aaaaaaaaaaaaaaaaa), Bbbbbbbbbbbbbbbb, metaclass=meta): pass -class Test( - # trailing class comment +class Test( # trailing class comment Aaaaaaaaaaaaaaaaa, # trailing comment # in between comment Bbbbbbbbbbbbbbbb, @@ -114,6 +276,189 @@ class TestTrailingComment1(Aaaa): # trailing comment class TestTrailingComment2: # trailing comment pass + + +class TestTrailingComment3[T]: # trailing comment + pass + + +class TestTrailingComment4[T](A): # trailing comment + pass + + +class Test: + """Docstring""" + + +class Test: + # comment + """Docstring""" + + +class Test: + """Docstring""" + + x = 1 + + +class Test: + """Docstring""" + + # comment + x = 1 + + +class Test: + + """Docstring""" + + +class Test: + # comment + + """Docstring""" + + +class Test: + # comment + + """Docstring""" + + +class Test: + + """Docstring""" + + x = 1 + + +class Test: + + """Docstring""" + + # comment + x = 1 + + +class C: # comment + pass + + +class C: # comment + pass + + +class C( + # comment +): + pass + + +class C: # comment + pass + + +class C( # comment + # comment + 1 +): + pass + + +class C( + 1 + # comment +): + pass + + +@dataclass +# Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +class AltCLIPOutput(ModelOutput): + ... + + +@dataclass +class AltCLIPOutput: # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP + ... + + +@dataclass +class AltCLIPOutput( + # Copied from transformers.models.clip.modeling_clip.CLIPOutput with CLIP->AltCLIP +): + ... + + +class TestTypeParams[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + Cccccccccccccccccccccc, +]: + pass + + +class TestTypeParams[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + *Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + **Cccccccccccccccccccccc, +]: + pass + + +class TestTypeParams[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +]: + pass + + +class TestTypeParams[ + *Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +]: + pass + + +class TestTypeParams[ + **Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +]: + pass + + +class TestTypeParams[**P, *Ts, T]: + pass + + +class TestTypeParams[ # trailing bracket comment + # leading comment + A, + # in between comment + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +]: + pass + + +class TestTypeParams[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +](B, C, D): + pass + + +class TestTypeParams[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +]( + Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + Cccccccccccccccccccccccc, + Ddddddddddddddddddddddddd, +): + pass + + +class TestTypeParams[A, B, C](meta=Aaaaaaaaaaaaaaaaaaaaaa): + pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__delete.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__delete.py.snap index b257c6486f864..ce4add0b9462c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__delete.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__delete.py.snap @@ -79,6 +79,10 @@ del ( del ( # dangling end of line comment ) + +del ( # dangling end of line comment + # dangling own line comment +) # trailing statement comment ``` ## Output @@ -217,6 +221,10 @@ del ( del ( # dangling end of line comment ) + +del ( # dangling end of line comment + # dangling own line comment +) # trailing statement comment ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__ellipsis.pyi.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__ellipsis.pyi.snap new file mode 100644 index 0000000000000..543c45b5c95a3 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__ellipsis.pyi.snap @@ -0,0 +1,193 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ellipsis.pyi +--- +## Input +```py +"""Compound statements with no body should be written on one line.""" + +if True: + ... +elif True: + ... +else: + ... + +if True: + # comment + ... +elif True: + # comment + ... +else: + # comment + ... + +if True: + ... # comment +elif True: + ... # comment +else: + ... # comment + +for i in []: + ... +else: + ... + +for i in []: + # comment + ... +else: + # comment + ... + +for i in []: + ... # comment +else: + ... # comment + +while True: + ... +else: + ... + +while True: + # comment + ... +else: + # comment + ... + +while True: + ... # comment +else: + ... # comment + +with True: + ... + +with True: + # comment + ... + +with True: + ... # comment + +match x: + case 1: + ... + case 2: + # comment + ... + case 3: + ... # comment + +try: + ... +except: + ... +finally: + ... + +try: + # comment + ... +except: + # comment + ... +finally: + # comment + ... + +try: + ... # comment +except: + ... # comment +finally: + ... # comment``` + +## Output +```py +"""Compound statements with no body should be written on one line.""" + +if True: ... +elif True: ... +else: ... + +if True: + # comment + ... +elif True: + # comment + ... +else: + # comment + ... + +if True: ... # comment +elif True: ... # comment +else: ... # comment + +for i in []: ... +else: ... + +for i in []: + # comment + ... +else: + # comment + ... + +for i in []: ... # comment +else: ... # comment + +while True: ... +else: ... + +while True: + # comment + ... +else: + # comment + ... + +while True: ... # comment +else: ... # comment + +with True: ... + +with True: + # comment + ... + +with True: ... # comment + +match x: + case 1: ... + case 2: + # comment + ... + case 3: ... # comment + +try: ... +except: ... +finally: ... + +try: + # comment + ... +except: + # comment + ... +finally: + # comment + ... + +try: ... # comment +except: ... # comment +finally: ... # comment +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__for.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__for.py.snap index 637372d81f956..f76bbc6405899 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__for.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__for.py.snap @@ -38,6 +38,44 @@ for (x, y) in (z, w): # type comment for x in (): # type: int ... + +# Tuple parentheses for iterable. +for x in 1, 2, 3: + pass + +for x in (1, 2, 3): + pass + +for x in 1, 2, 3,: + pass + +# Don't keep parentheses around right target if it can made fit by breaking sub expressions +for column_name, ( + referenced_column_name, + referenced_table_name, +) in relations.items(): + pass + +for column_name, [ + referenced_column_name, + referenced_table_name, +] in relations.items(): + pass + +for column_name, [ + referenced_column_name, + referenced_table_name, +], in relations.items(): + pass + +for ( + # leading comment + column_name, [ + referenced_column_name, + referenced_table_name, +]) in relations.items(): + pass + ``` ## Output @@ -76,6 +114,52 @@ for x, y in (z, w): # type comment for x in (): # type: int ... + +# Tuple parentheses for iterable. +for x in 1, 2, 3: + pass + +for x in (1, 2, 3): + pass + +for x in ( + 1, + 2, + 3, +): + pass + +# Don't keep parentheses around right target if it can made fit by breaking sub expressions +for column_name, ( + referenced_column_name, + referenced_table_name, +) in relations.items(): + pass + +for column_name, [ + referenced_column_name, + referenced_table_name, +] in relations.items(): + pass + +for ( + column_name, + [ + referenced_column_name, + referenced_table_name, + ], +) in relations.items(): + pass + +for ( + # leading comment + column_name, + [ + referenced_column_name, + referenced_table_name, + ], +) in relations.items(): + pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__function.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__function.py.snap index 31226f41f7aa7..d801c863eba23 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__function.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__function.py.snap @@ -72,6 +72,52 @@ def argument_with_long_type_annotation( def test(): ... +# Type parameter empty line spacing +def test[ + # comment + A, + + # another + + B, +](): ... + + +# Type parameter comments +def type_param_comments[ # trailing bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +](): + # body comment + pass + + +# Note empty type parameters is not valid syntax, e.g. +# def test[](): ... + + +# Different type parameter wrappings + +def single_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccccccccc](): + pass + +def params_on_their_own_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccc, Ddddddddddddd, Eeeeeeee](): + pass + +def param_per_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccccccccc, Ddddddddddddd, Eeeeeeeeeeeeeeeee, ffffffffffff](): + pass + +def single_line_trailing_comma[A, B, C,](): + pass + # Comment def with_leading_comment(): ... @@ -237,6 +283,105 @@ def f42( c, ): pass + + +# Check trailing commas are permitted in funcdef argument list. +def f(a, ): pass +def f(*args, ): pass +def f(**kwds, ): pass +def f(a, *args, ): pass +def f(a, **kwds, ): pass +def f(*args, b, ): pass +def f(*, b, ): pass +def f(*args, **kwds, ): pass +def f(a, *args, b, ): pass +def f(a, *, b, ): pass +def f(a, *args, **kwds, ): pass +def f(*args, b, **kwds, ): pass +def f(*, b, **kwds, ): pass +def f(a, *args, b, **kwds, ): pass +def f(a, *, b, **kwds, ): pass + +# Handle comments on open parenthesis. +def f( + # first + # second +): + ... + + +def f( # first + # second +): # third + ... + + +def f( # first +): # second + ... + + +def f( + a, + /, + # first + b + # second +): + ... + + +def f( # first + *, + # second + b + # third +): + ... + + +def f( # first + # second + *, + # third + b + # fourth +): + ... + + +def f( # first + a, + # second +): # third + ... + + +def f( # first + a +): # second + ... + + +def f( # first + a + # second +): # third + ... + + +def f( # first + a, + / # second + , + # third +): + ... + +# Walrus operator in return type. +def this_is_unusual() -> (please := no): ... + +def this_is_unusual(x) -> (please := no): ... ``` ## Output @@ -335,6 +480,70 @@ def test(): ... +# Type parameter empty line spacing +def test[ + # comment + A, + # another + B, +](): + ... + + +# Type parameter comments +def type_param_comments[ # trailing bracket comment + # leading comment + A, + # in between comment + B, + # another leading comment + C, + D, # trailing comment + # leading bracket comment +](): + # body comment + pass + + +# Note empty type parameters is not valid syntax, e.g. +# def test[](): ... + + +# Different type parameter wrappings + +def single_line[Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbbbb, Ccccccccccccccccc](): + pass + + +def params_on_their_own_line[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Bbbbbbbbbbbbbbb, + Ccccccccccc, + Ddddddddddddd, + Eeeeeeee, +](): + pass + + +def param_per_line[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Bbbbbbbbbbbbbbb, + Ccccccccccccccccc, + Ddddddddddddd, + Eeeeeeeeeeeeeeeee, + ffffffffffff, +](): + pass + + +def single_line_trailing_comma[ + A, + B, + C, +](): + pass + + # Comment def with_leading_comment(): ... @@ -344,6 +553,7 @@ def with_leading_comment(): # looking from the position of the if # Regression test for https://github.com/python/cpython/blob/ad56340b665c5d8ac1f318964f71697bba41acb7/Lib/logging/__init__.py#L253-L260 if True: + def f1(): pass # a else: @@ -351,6 +561,7 @@ else: # Here it's actually a trailing comment if True: + def f2(): pass # a @@ -511,6 +722,203 @@ def f42( c, ): pass + + +# Check trailing commas are permitted in funcdef argument list. +def f( + a, +): + pass + + +def f( + *args, +): + pass + + +def f( + **kwds, +): + pass + + +def f( + a, + *args, +): + pass + + +def f( + a, + **kwds, +): + pass + + +def f( + *args, + b, +): + pass + + +def f( + *, + b, +): + pass + + +def f( + *args, + **kwds, +): + pass + + +def f( + a, + *args, + b, +): + pass + + +def f( + a, + *, + b, +): + pass + + +def f( + a, + *args, + **kwds, +): + pass + + +def f( + *args, + b, + **kwds, +): + pass + + +def f( + *, + b, + **kwds, +): + pass + + +def f( + a, + *args, + b, + **kwds, +): + pass + + +def f( + a, + *, + b, + **kwds, +): + pass + + +# Handle comments on open parenthesis. +def f( + # first + # second +): + ... + + +def f( # first + # second +): # third + ... + + +def f( # first +): # second + ... + + +def f( + a, + /, + # first + b, + # second +): + ... + + +def f( # first + *, + # second + b, + # third +): + ... + + +def f( # first + # second + *, + # third + b, + # fourth +): + ... + + +def f( # first + a, + # second +): # third + ... + + +def f( # first + a +): # second + ... + + +def f( # first + a, + # second +): # third + ... + + +def f( # first + a, + # third + /, # second +): + ... + + +# Walrus operator in return type. +def this_is_unusual() -> (please := no): + ... + + +def this_is_unusual(x) -> (please := no): + ... ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__global.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__global.py.snap index 1181cdba309ae..1209b7c3f5a86 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__global.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__global.py.snap @@ -16,6 +16,10 @@ def f(): def f(): global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + + +def f(): + global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment ``` ## Output @@ -31,7 +35,16 @@ def f(): def f(): - global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + global \ + analyze_featuremap_layer, \ + analyze_featuremapcompression_layer, \ + analyze_latencies_post, \ + analyze_motions_layer, \ + analyze_size_model + + +def f(): + global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap index 3452bfe9b8a86..9c459694dd9e5 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap @@ -109,6 +109,18 @@ else: if True: print("a") # 1 elif True: print("b") # 2 else: print("c") # 3 + +# Regression test for https://github.com/astral-sh/ruff/issues/5337 +if parent_body: + if current_body: + child_in_body() + last_child_in_current_body() # may or may not have children on its own +# a + # b + # c + # d + # e + #f ``` ## Output @@ -203,14 +215,17 @@ def f(): if True: + def f(): pass # 1 elif True: + def f(): pass # 2 else: + def f(): pass # 3 @@ -221,6 +236,18 @@ elif True: print("b") # 2 else: print("c") # 3 + +# Regression test for https://github.com/astral-sh/ruff/issues/5337 +if parent_body: + if current_body: + child_in_body() + last_child_in_current_body() # may or may not have children on its own + # e + # f + # c + # d +# a +# b ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap index 020860638336b..5b3177fc5d3ed 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap @@ -7,12 +7,67 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd + +# At the top-level, force one empty line after an import, but allow up to two empty +# lines. +import os +import sys +x = 1 + +import os +import sys + +x = 1 + +import os +import sys + + +x = 1 + +import os +import sys + + + +x = 1 + + +# In a nested scope, force one empty line after an import. +def func(): + import os + import sys + x = 1 + + +def func(): + import os + import sys + + x = 1 + + +def func(): + import os + import sys + + + x = 1 + + +def func(): + import os + import sys + + + + x = 1 ``` ## Output ```py from a import ( - aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, ) from a import ( aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, @@ -22,6 +77,59 @@ from a import ( aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, ) + +# At the top-level, force one empty line after an import, but allow up to two empty +# lines. +import os +import sys + +x = 1 + +import os +import sys + +x = 1 + +import os +import sys + + +x = 1 + +import os +import sys + + +x = 1 + + +# In a nested scope, force one empty line after an import. +def func(): + import os + import sys + + x = 1 + + +def func(): + import os + import sys + + x = 1 + + +def func(): + import os + import sys + + x = 1 + + +def func(): + import os + import sys + + x = 1 ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap index 0d8c90572e987..6b3942ea0c9ea 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap @@ -20,6 +20,27 @@ from a import ( aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, ) from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * + + +from a import bar # comment + +from a import bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar # comment + +from a import ( # comment + bar, +) + +from a import ( # comment + bar +) + +from a import bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar, bar +# comment + +from a import \ + ( # comment + bar, +) ``` ## Output @@ -40,6 +61,60 @@ from a import ( aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, ) from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * + + +from a import bar # comment + +from a import ( + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, +) # comment + +from a import ( # comment + bar, +) + +from a import ( # comment + bar, +) + +from a import ( + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, + bar, +) +# comment + +from a import ( # comment + bar, +) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap new file mode 100644 index 0000000000000..5f2bb3ae52955 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap @@ -0,0 +1,831 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py +--- +## Input +```py +# leading match comment +match foo: # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # leading expr comment + # another leading expr comment + foo # trailing expr comment + # another trailing expr comment +): # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # hello + foo # trailing expr comment + , # another +): # dangling match comment + case "bar": + pass + + +match [ # comment + first, + second, + third +]: # another comment + case ["a", "b", "c"]: + pass + +match ( # comment + "a b c" +).split(): # another comment + case ["a", "b", "c"]: + pass + + +match ( # comment + # let's go + yield foo +): # another comment + case ["a", "b", "c"]: + pass + + +match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment + case "sshhhhhhhh": + pass + + +def foo(): + match inside_func: # comment + case "bar": + pass + + +match newlines: + + # case 1 leading comment + + + case "top level case comment with newlines": # case dangling comment + # pass leading comment + pass + # pass trailing comment + + + # case 2 leading comment + + + + case "case comment with newlines" if foo == 2: # second + pass + + case "one", "newline" if (foo := 1): # third + pass + + + case "two newlines": + pass + + + + case "three newlines": + pass + case _: + pass + + +match long_lines: + case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment + pass + + case "this is a long line for if condition with parentheses" if (aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2): # comment + pass + + case "named expressions aren't special" if foo := 1: + pass + + case "named expressions aren't that special" if (foo := 1): + pass + + case "but with already broken long lines" if ( + aaaaaaahhhhhhhhhhh == 1 and + bbbbbbbbaaaaaahhhh == 2 + ): # another comment + pass + + +match pattern_comments: + case ( + only_trailing # trailing 1 + # trailing 2 +# trailing 3 + ): + pass + + +match pattern_comments: + case ( # leading + only_leading + ): + pass + + +match pattern_comments: + case ( + # leading + leading_and_trailing # trailing 1 + # trailing 2 +# trailing 3 + ): + pass + + +match pattern_comments: + case ( + no_comments + ): + pass + + +match pattern_comments: + case ( + # 1 + pattern # 2 + # 3 + as # 4 + # 5 + name # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as # 2 + # 3 + name #4 + # 5 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as + # 2 + name + # 3 + ): + pass + + +match subject: + case ( + pattern # 1 + as # 2 + name # 3 + ): + pass + + +match x: + case (a as b) as c: + pass + + +match pattern_singleton: + case ( + # leading 1 + # leading 2 + None # trailing + # trailing own 1 + # trailing own 2 + ): + pass + case ( + True # trailing + ): + ... + case False: + ... + + +match foo: + case "a", "b": + pass + case "a", "b",: + pass + case ("a", "b"): + pass + case ["a", "b"]: + pass + case (["a", "b"]): + pass + + +match foo: + case [ # leading +# leading + # leading + # leading + "a", # trailing +# trailing + # trailing + # trailing + "b", + ]: + pass + +match foo: + case 1: + y = 0 + case (1): + y = 1 + case (("a")): + y = 1 + case ( # comment + 1 + ): + y = 1 + case ( + # comment + 1 + ): + y = 1 + case ( + 1 # comment + ): + y = 1 + case ( + 1 + # comment + ): + y = 1 + + +match foo: + case [1, 2, *rest]: + pass + case [1, 2, *_]: + pass + case [*rest, 1, 2]: + pass + case [*_, 1, 2]: + pass + case [ + 1, + 2, + *rest, + ]: + pass + case [1, 2, * # comment + rest]: + pass + case [1, 2, * # comment + _]: + pass + case [* # comment + rest, 1, 2]: + pass + case [* # comment + _, 1, 2]: + pass + case [* # end of line + # own line + _, 1, 2]: + pass + case [* # end of line + # own line + _, 1, 2]: + pass + + +match foo: + case (1): + pass + case ((1)): + pass + case [(1), 2]: + pass + case [( # comment + 1 + ), 2]: + pass + case [ # outer + ( # inner + 1 + ), 2]: + pass + case [ + ( # outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + ( # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + # own line + ( # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [(*rest), (a as b)]: + pass + + +match foo: + case {"a": 1, "b": 2}: + pass + + case { + # own line + "a": 1, # end-of-line + # own line + "b": 2, + }: + pass + + case { # open + 1 # key + : # colon + value # value + }: + pass + + case {**d}: + pass + + case { + ** # middle with single item + b + }: + pass + + case { + # before + ** # between + b, + }: + pass + + case { + 1: x, + # foo + ** # bop + # before + b, # boo + # baz + }: + pass + + case { + 1: x + # foo + , + ** + b, + }: + pass +``` + +## Output +```py +# leading match comment +match foo: # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # leading expr comment + # another leading expr comment + foo # trailing expr comment + # another trailing expr comment +): # dangling match comment + case "bar": + pass + + +# leading match comment +match ( # hello + foo, # trailing expr comment # another +): # dangling match comment + case "bar": + pass + + +match [ # comment + first, + second, + third, +]: # another comment + case ["a", "b", "c"]: + pass + +match ( # comment + "a b c" +).split(): # another comment + case ["a", "b", "c"]: + pass + + +match ( # comment + # let's go + yield foo +): # another comment + case ["a", "b", "c"]: + pass + + +match aaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh: # comment + case "sshhhhhhhh": + pass + + +def foo(): + match inside_func: # comment + case "bar": + pass + + +match newlines: + # case 1 leading comment + + case "top level case comment with newlines": # case dangling comment + # pass leading comment + pass + # pass trailing comment + + # case 2 leading comment + + case "case comment with newlines" if foo == 2: # second + pass + + case "one", "newline" if (foo := 1): # third + pass + + case "two newlines": + pass + + case "three newlines": + pass + case _: + pass + + +match long_lines: + case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment + pass + + case "this is a long line for if condition with parentheses" if ( + aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2 + ): # comment + pass + + case "named expressions aren't special" if foo := 1: + pass + + case "named expressions aren't that special" if (foo := 1): + pass + + case "but with already broken long lines" if ( + aaaaaaahhhhhhhhhhh == 1 and bbbbbbbbaaaaaahhhh == 2 + ): # another comment + pass + + +match pattern_comments: + case ( + only_trailing # trailing 1 + # trailing 2 + # trailing 3 + ): + pass + + +match pattern_comments: + case ( # leading + only_leading + ): + pass + + +match pattern_comments: + case ( + # leading + leading_and_trailing # trailing 1 + # trailing 2 + # trailing 3 + ): + pass + + +match pattern_comments: + case no_comments: + pass + + +match pattern_comments: + case ( + # 1 + pattern # 2 + # 3 + as # 4 + # 5 + name # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as # 2 + # 3 + name # 4 + # 5 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as + # 2 + name + # 3 + ): + pass + + +match subject: + case ( + pattern # 1 + as # 2 + name # 3 + ): + pass + + +match x: + case (a as b) as c: + pass + + +match pattern_singleton: + case ( + # leading 1 + # leading 2 + None # trailing + # trailing own 1 + # trailing own 2 + ): + pass + case True: # trailing + ... + case False: + ... + + +match foo: + case "a", "b": + pass + case ( + "a", + "b", + ): + pass + case ("a", "b"): + pass + case ["a", "b"]: + pass + case ["a", "b"]: + pass + + +match foo: + case [ # leading + # leading + # leading + # leading + "a", # trailing + # trailing + # trailing + # trailing + "b", + ]: + pass + +match foo: + case 1: + y = 0 + case 1: + y = 1 + case "a": + y = 1 + case ( # comment + 1 + ): + y = 1 + case ( + # comment + 1 + ): + y = 1 + case 1: # comment + y = 1 + case ( + 1 + # comment + ): + y = 1 + + +match foo: + case [1, 2, *rest]: + pass + case [1, 2, *_]: + pass + case [*rest, 1, 2]: + pass + case [*_, 1, 2]: + pass + case [ + 1, + 2, + *rest, + ]: + pass + case [ + 1, + 2, + * # comment + rest, + ]: + pass + case [ + 1, + 2, + * # comment + _, + ]: + pass + case [ + * # comment + rest, + 1, + 2, + ]: + pass + case [ + * # comment + _, + 1, + 2, + ]: + pass + case [ + * # end of line + # own line + _, + 1, + 2, + ]: + pass + case [ + * # end of line + # own line + _, + 1, + 2, + ]: + pass + + +match foo: + case 1: + pass + case 1: + pass + case [(1), 2]: + pass + case [ + ( # comment + 1 + ), + 2, + ]: + pass + case [ # outer + ( # inner + 1 + ), + 2, + ]: + pass + case [ + ( # outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + ( # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [ # outer + ( + # own line + # inner outer + [ # inner + 1, + ] + ) + ]: + pass + case [(*rest), (a as b)]: + pass + + +match foo: + case {"a": 1, "b": 2}: + pass + + case { + # own line + "a": 1, # end-of-line + # own line + "b": 2, + }: + pass + + case { # open + 1: value # key # colon # value + }: + pass + + case {**d}: + pass + + case { + # middle with single item + **b + }: + pass + + case { + # before + # between + **b, + }: + pass + + case { + 1: x, + # foo + # bop + # before + **b, # boo + # baz + }: + pass + + case { + 1: x, + # foo + **b, + }: + pass +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__nonlocal.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__nonlocal.py.snap index fbffb2ede9ffe..bbdcb3046d383 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__nonlocal.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__nonlocal.py.snap @@ -16,6 +16,10 @@ def f(): def f(): nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + + +def f(): + nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment ``` ## Output @@ -31,7 +35,16 @@ def f(): def f(): - nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + nonlocal \ + analyze_featuremap_layer, \ + analyze_featuremapcompression_layer, \ + analyze_latencies_post, \ + analyze_motions_layer, \ + analyze_size_model + + +def f(): + nonlocal analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model # end-of-line comment ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__raise.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__raise.py.snap index a90849f43ba08..46637a35435a4 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__raise.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__raise.py.snap @@ -154,8 +154,7 @@ raise ( ) -raise ( - # hey +raise ( # hey aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # Holala + bbbbbbbbbbbbbbbbbbbbbbbbbb # stay @@ -165,8 +164,7 @@ raise ( ) # whaaaaat # the end -raise ( - # hey 2 +raise ( # hey 2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # Holala "bbbbbbbbbbbbbbbbbbbbbbbb" # stay @@ -201,11 +199,11 @@ raise ( # sould I stay here # just a comment here ) # trailing comment -raise hello() # sould I stay here -# just a comment here # trailing comment +raise hello( # sould I stay here + # just a comment here +) # trailing comment -raise ( - # sould I stay here +raise ( # sould I stay here test, # just a comment here ) # trailing comment diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__return_annotation.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__return_annotation.py.snap new file mode 100644 index 0000000000000..b2fc7448944c5 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__return_annotation.py.snap @@ -0,0 +1,521 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/return_annotation.py +--- +## Input +```py +# Handle comments on empty tuple return types. +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + # comment +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + 1 +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + 1, 2 +): ... + +def zrevrangebylex(self, name: _Key, max: _Value, min: _Value, start: int | None = None, num: int | None = None) -> ( # type: ignore[override] + (1, 2) +): ... + +def handleMatch( # type: ignore[override] # https://github.com/python/mypy/issues/10197 + self, m: Match[str], data: str +) -> Union[Tuple[None, None, None], Tuple[Element, int, int]]: + ... + +def double(a: int # Hello +) -> (int): + return 2 * a + +def double(a: int) -> ( # Hello + int +): + return 2*a + +def double(a: int) -> ( # Hello +): + return 2*a + +# Breaking over parameters and return types. (Black adds a trailing comma when the +# function arguments break here with a single argument; we do not.) +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a: + ... + +def f(a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> a: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a: + ... + +# Breaking return type annotations. Black adds parentheses if the parameters are +# empty; otherwise, it leverages the expressions own parentheses if possible. +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(*args) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( # foo +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + # bar +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X + Y + foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X + Y + foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X and Y and foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X and Y and foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (X | Y | foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> (X | Y | foooooooooooooooooooooooooooooooooooo()): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + + +def double() -> first_item and foo.bar.baz().bop(1,): + return 2 * a + + +# Dangling comments on return annotations. +def double(a: int) -> ( + int # Hello +): + return 2*a + +def double(a: int) -> ( + foo.bar # Hello +): + return 2*a + +def double(a: int) -> ( + [int] # Hello +): + return 2*a + +def double(a: int) -> ( + int | list[int] # Hello +): + pass + +def double(a: int) -> ( + int | list[int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int] # Hello +): + pass +``` + +## Output +```py +# Handle comments on empty tuple return types. +def zrevrangebylex( + self, + name: _Key, + max: _Value, + min: _Value, + start: int | None = None, + num: int | None = None, +) -> ( # type: ignore[override] +): + ... + + +def zrevrangebylex( + self, + name: _Key, + max: _Value, + min: _Value, + start: int | None = None, + num: int | None = None, +) -> ( # type: ignore[override] + # comment +): + ... + + +def zrevrangebylex( + self, + name: _Key, + max: _Value, + min: _Value, + start: int | None = None, + num: int | None = None, +) -> ( # type: ignore[override] + 1 +): + ... + + +def zrevrangebylex( + self, + name: _Key, + max: _Value, + min: _Value, + start: int | None = None, + num: int | None = None, +) -> ( # type: ignore[override] + 1, + 2, +): + ... + + +def zrevrangebylex( + self, + name: _Key, + max: _Value, + min: _Value, + start: int | None = None, + num: int | None = None, +) -> ( # type: ignore[override] + (1, 2) +): + ... + + +def handleMatch( # type: ignore[override] # https://github.com/python/mypy/issues/10197 + self, m: Match[str], data: str +) -> Union[Tuple[None, None, None], Tuple[Element, int, int]]: + ... + + +def double( + a: int, # Hello +) -> int: + return 2 * a + + +def double( + a: int +) -> ( # Hello + int +): + return 2 * a + + +def double( + a: int +) -> ( # Hello +): + return 2 * a + + +# Breaking over parameters and return types. (Black adds a trailing comma when the +# function arguments break here with a single argument; we do not.) +def f( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + + +def f( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a +) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + + +def f( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) -> a: + ... + + +def f( + a +) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + ... + + +def f[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +]() -> a: + ... + + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: + ... + + +def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +) -> a: + ... + + +# Breaking return type annotations. Black adds parentheses if the parameters are +# empty; otherwise, it leverages the expressions own parentheses if possible. +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ] +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ] +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ] +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + *args +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( # foo +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + # bar +) -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> X + Y + foooooooooooooooooooooooooooooooooooo(): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> X + Y + foooooooooooooooooooooooooooooooooooo(): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + X and Y and foooooooooooooooooooooooooooooooooooo() +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> X and Y and foooooooooooooooooooooooooooooooooooo(): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> X | Y | foooooooooooooooooooooooooooooooooooo(): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> X | Y | foooooooooooooooooooooooooooooooooooo(): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + + +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx( + x +) -> ( + X | Y | foooooooooooooooooooooooooooooooooooo() # comment +): + ... + + +def double() -> ( + first_item + and foo.bar.baz().bop( + 1, + ) +): + return 2 * a + + +# Dangling comments on return annotations. +def double( + a: int +) -> ( + int # Hello +): + return 2 * a + + +def double( + a: int +) -> ( + foo.bar # Hello +): + return 2 * a + + +def double( + a: int +) -> ( + [int] # Hello +): + return 2 * a + + +def double( + a: int +) -> ( + int | list[int] # Hello +): + pass + + +def double( + a: int +) -> ( + int + | list[ + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int + ] # Hello +): + pass +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.py.snap new file mode 100644 index 0000000000000..735d40d806f28 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.py.snap @@ -0,0 +1,118 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.py +--- +## Input +```py +class A: + def __init__(self): + pass + +class B: + def __init__(self): + pass + +def foo(): + pass + +class Del(expr_context): ... +class Load(expr_context): ... + +# Some comment. +class Other(expr_context): ... +class Store(expr_context): ... +class Foo(Bar): ... + +class Baz(Qux): + def __init__(self): + pass + +class Quux(Qux): + def __init__(self): + pass + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + +def bar(): ... +def baz(): ... +def quux(): + """Some docstring.""" + +def quuz(): + """Some docstring.""" +``` + +## Output +```py +class A: + def __init__(self): + pass + + +class B: + def __init__(self): + pass + + +def foo(): + pass + + +class Del(expr_context): + ... + + +class Load(expr_context): + ... + + +# Some comment. +class Other(expr_context): + ... + + +class Store(expr_context): + ... + + +class Foo(Bar): + ... + + +class Baz(Qux): + def __init__(self): + pass + + +class Quux(Qux): + def __init__(self): + pass + + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + + +def bar(): + ... + + +def baz(): + ... + + +def quux(): + """Some docstring.""" + + +def quuz(): + """Some docstring.""" +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.pyi.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.pyi.snap new file mode 100644 index 0000000000000..2e301df56a8f8 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__top_level.pyi.snap @@ -0,0 +1,165 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/top_level.pyi +--- +## Input +```py +class A: + def __init__(self): + pass + + +class B: + def __init__(self): + pass + + +def foo(): + pass + + +class Del(expr_context): + ... + + +class Load(expr_context): + ... + + +# Some comment. +class Other(expr_context): + ... + + +class Store(expr_context): + ... + + +class Foo(Bar): + ... + + +class Baz(Qux): + def __init__(self): + pass + + +class Quux(Qux): + def __init__(self): + pass + + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + + +def bar(): + ... + + +def baz(): + ... + + +def quux(): + """Some docstring.""" + + +def quuz(): + """Some docstring.""" + +def a(): + ... + +class Test: + ... + +class Test2(A): + ... + +def b(): ... +# comment +def c(): ... + +class EllipsisWithComment: + ... # comment + +def function_with_comment(): + ... # comment + +class EllispsisWithMultipleTrailing: # trailing class comment + ... # trailing ellipsis comment + +class EllipsisWithLeadingComment: + # leading + ... +``` + +## Output +```py +class A: + def __init__(self): + pass + +class B: + def __init__(self): + pass + +def foo(): + pass + +class Del(expr_context): ... +class Load(expr_context): ... + +# Some comment. +class Other(expr_context): ... +class Store(expr_context): ... +class Foo(Bar): ... + +class Baz(Qux): + def __init__(self): + pass + +class Quux(Qux): + def __init__(self): + pass + +# Some comment. +class Quuz(Qux): + def __init__(self): + pass + +def bar(): ... +def baz(): ... +def quux(): + """Some docstring.""" + +def quuz(): + """Some docstring.""" + +def a(): ... + +class Test: ... +class Test2(A): ... + +def b(): ... + +# comment +def c(): ... + +class EllipsisWithComment: ... # comment + +def function_with_comment(): ... # comment + +class EllispsisWithMultipleTrailing: # trailing class comment + ... # trailing ellipsis comment + +class EllipsisWithLeadingComment: + # leading + ... +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap index 9f9afbc4a2990..589d8a25e754c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap @@ -144,6 +144,34 @@ else: # 7 preceding: last in body, following: fist in alt body, enclosing: exc print(3) # 8 preceding: last in body, following: fist in alt body, enclosing: try finally: # 9 preceding: last in body, following: fist in alt body, enclosing: try print(3) # 10 preceding: last in body, following: any, enclosing: try + +try: + pass +except ( + ZeroDivisionError + # comment +): + pass + + +try: + pass + +finally: + pass + + +try: + pass + +except ZeroDivisonError: + pass + +else: + pass + +finally: + pass ``` ## Output @@ -263,18 +291,22 @@ except RuntimeError: raise try: + def f(): pass # a except: + def f(): pass # b else: + def f(): pass # c finally: + def f(): pass # d @@ -300,6 +332,34 @@ else: # 7 preceding: last in body, following: fist in alt body, enclosing: exc print(3) # 8 preceding: last in body, following: fist in alt body, enclosing: try finally: # 9 preceding: last in body, following: fist in alt body, enclosing: try print(3) # 10 preceding: last in body, following: any, enclosing: try + +try: + pass +except ( + ZeroDivisionError + # comment +): + pass + + +try: + pass + +finally: + pass + + +try: + pass + +except ZeroDivisonError: + pass + +else: + pass + +finally: + pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap index 163c14fdda258..1009367aa6170 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap @@ -4,7 +4,7 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/ --- ## Input ```py -# Copied from https://github.com/RustPython/Parser/blob/704eb40108239a8faf9bd1d4217e8dad0ac7edb3/parser/src/parser.rs#L901-L936 +# basic usage type X = int type X = int | str @@ -16,6 +16,17 @@ type X[T, *Ts, **P] = (T, Ts, P) type X[T: int, *Ts, **P] = (T, Ts, P) type X[T: (int, str), *Ts, **P] = (T, Ts, P) +# long name +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[A] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt + +# long value +type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type X = Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + # soft keyword as alias name type type = int type match = int @@ -42,40 +53,185 @@ type X \ [T] = T type X[T] \ = T + +# type leading comment +type X = ( # trailing open paren comment + # value leading comment + int # value trailing comment + # leading close paren comment +) # type trailing comment + + +# type leading comment +type X = ( + # value leading comment + int # value trailing comment + + # leading close paren comment +) + +# type parameters +type type_params_single_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc] = int +type type_params_arguments_on_their_own_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccc, ddddddddddddd, eeeeeee] = int +type type_params_argument_per_line[aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc, ddddddddddddd, eeeeeeeeeeeeeeee, ffffffffffff] = int +type type_params_trailing_comma[a, b,] = int +type type_params_comments[ # trailing open bracket comment + # leading comment + A, + + # in between comment + + B, + # another leading comment + C, + D, # trailing comment + # leading close bracket comment +] = int # trailing value comment +type type_params_all_kinds[type_var, *type_var_tuple, **param_spec] = int + +# type variable bounds +type bounds_single_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc)] = T +type bounds_arguments_on_their_own_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccc, ddddddddddddd, eeeeeee)] = T +type bounds_argument_per_line[T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc, ddddddddddddd, eeeeeeeeeeeeeeee, ffffffffffff)] = T +type bounds_trailing_comma[T: (a, b,)] = T ``` ## Output ```py -# Copied from https://github.com/RustPython/Parser/blob/704eb40108239a8faf9bd1d4217e8dad0ac7edb3/parser/src/parser.rs#L901-L936 - -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int # recursive -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int +# basic usage + +type X = int +type X = int | str +type X = int | "ForwardRefY" +type X[T] = T | list[X[T]] # recursive +type X[T] = int +type X[T] = list[T] | set[T] +type X[T, *Ts, **P] = (T, Ts, P) +type X[T: int, *Ts, **P] = (T, Ts, P) +type X[T: (int, str), *Ts, **P] = (T, Ts, P) + +# long name +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[ + A +] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaa +] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[ + Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Bbbbbbbbbbbbb, +] = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt + +# long value +type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type X = ( + Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +) # soft keyword as alias name -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int +type type = int +type match = int +type case = int # soft keyword as value -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int +type foo = type +type foo = match +type foo = case # multine definitions -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int -type NOT_YET_IMPLEMENTED_type_alias = int +type X = int +type X = int +type X = int +type X = int +type X[T] = T +type X[T] = T +type X[T] = T + +# type leading comment +type X = ( # trailing open paren comment + # value leading comment + int # value trailing comment + # leading close paren comment +) # type trailing comment + + +# type leading comment +type X = ( + # value leading comment + int # value trailing comment + # leading close paren comment +) + +# type parameters +type type_params_single_line[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbb, + ccccccccccccccccc, +] = int +type type_params_arguments_on_their_own_line[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbb, + ccccccccccc, + ddddddddddddd, + eeeeeee, +] = int +type type_params_argument_per_line[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbb, + ccccccccccccccccc, + ddddddddddddd, + eeeeeeeeeeeeeeee, + ffffffffffff, +] = int +type type_params_trailing_comma[ + a, + b, +] = int +type type_params_comments[ # trailing open bracket comment + # leading comment + A, + # in between comment + B, + # another leading comment + C, + D, # trailing comment + # leading close bracket comment +] = int # trailing value comment +type type_params_all_kinds[type_var, *type_var_tuple, **param_spec] = int + +# type variable bounds +type bounds_single_line[ + T: (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, ccccccccccccccccc) +] = T +type bounds_arguments_on_their_own_line[ + T: ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbb, + ccccccccccc, + ddddddddddddd, + eeeeeee, + ) +] = T +type bounds_argument_per_line[ + T: ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbb, + ccccccccccccccccc, + ddddddddddddd, + eeeeeeeeeeeeeeee, + ffffffffffff, + ) +] = T +type bounds_trailing_comma[ + T: ( + a, + b, + ) +] = T ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__with.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__with.py.snap index 3140929dc1080..1c54019b650d1 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__with.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__with.py.snap @@ -73,6 +73,24 @@ with ( a as b ): ... +with ( + a as b + # trailing comment +): ... + +with ( + a as ( + # leading comment + b + ) +): ... + +with ( + a as ( + b + # trailing comment + ) +): ... with (a # trailing same line comment # trailing own line comment @@ -84,7 +102,6 @@ with ( as b ): ... - with (a # trailing same line comment # trailing own line comment ) as b: ... @@ -114,7 +131,6 @@ with ( ): ... - with [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", @@ -122,6 +138,128 @@ with [ dddddddddddddddddddddddddddddddd, ] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2: ... + +# Comments on open parentheses +with ( # comment + CtxManager1() as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ) as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + CtxManager() +) as example: + ... + +with ( # outer comment + CtxManager() +) as example, ( # inner comment + CtxManager2() +) as example2: + ... + +with ( # outer comment + CtxManager1(), + CtxManager2(), +) as example: + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ), + CtxManager2(), +) as example: + ... + +# Breaking of with items. +with (test # bar + as # foo + ( + # test + foo)): + pass + +with test as ( + # test + foo): + pass + +with (test # bar + as # foo + ( # baz + # test + foo)): + pass + +with (a as b, c as d): + pass + +with ( + a as b, + # foo + c as d +): + pass + +with ( + a as ( # foo + b + ) +): + pass + +with ( + f(a, ) as b + +): + pass + +with (x := 1) as d: + pass + +with (x[1, 2,] as d): + pass + +with (f(a, ) as b, c as d): + pass + +with f(a, ) as b, c as d: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) as b: + pass + +with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +) as b, c as d: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, c as d): + pass + +with ( + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) as b, c as d): + pass + +with (foo() as bar, baz() as bop): + pass ``` ## Output @@ -150,19 +288,19 @@ with ( with ( - a as # a # as - # own line - b, # b # comma + a as ( # a # as + # own line + b + ), # b # comma c, # c ): # colon ... # body # body trailing own -with ( - a as # a # as +with a as ( # a # as # own line - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # b -): + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +): # b pass @@ -197,6 +335,23 @@ with ( ): ... +with ( + a as b + # trailing comment +): + ... + +with a as ( + # leading comment + b +): + ... + +with a as ( + b + # trailing comment +): + ... with ( a # trailing same line comment @@ -210,7 +365,6 @@ with ( ) as b: ... - with ( a # trailing same line comment # trailing own line comment @@ -218,11 +372,11 @@ with ( ... with ( - ( - a - # trailing own line comment - ) as b # trailing as same line comment # trailing b same line comment -): + a + # trailing own line comment +) as ( # trailing as same line comment + b +): # trailing b same line comment ... with ( @@ -242,7 +396,6 @@ with ( ): ... - with [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", @@ -250,6 +403,136 @@ with [ dddddddddddddddddddddddddddddddd, ] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2: ... + +# Comments on open parentheses +with ( # comment + CtxManager1() as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ) as example1, + CtxManager2() as example2, + CtxManager3() as example3, +): + ... + +with ( # outer comment + CtxManager() +) as example: + ... + +with ( # outer comment + CtxManager() +) as example, ( # inner comment + CtxManager2() +) as example2: + ... + +with ( # outer comment + CtxManager1(), + CtxManager2(), +) as example: + ... + +with ( # outer comment + ( # inner comment + CtxManager1() + ), + CtxManager2(), +) as example: + ... + +# Breaking of with items. +with test as ( # bar # foo + # test + foo +): + pass + +with test as ( + # test + foo +): + pass + +with test as ( # bar # foo # baz + # test + foo +): + pass + +with a as b, c as d: + pass + +with ( + a as b, + # foo + c as d, +): + pass + +with a as ( # foo + b +): + pass + +with f( + a, +) as b: + pass + +with (x := 1) as d: + pass + +with x[ + 1, + 2, +] as d: + pass + +with ( + f( + a, + ) as b, + c as d, +): + pass + +with f( + a, +) as b, c as d: + pass + +with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b: + pass + +with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b: + pass + +with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, c as d: + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, + c as d, +): + pass + +with ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, + c as d, +): + pass + +with foo() as bar, baz() as bop: + pass ``` diff --git a/crates/ruff_python_index/Cargo.toml b/crates/ruff_python_index/Cargo.toml index 10d8813ce40ad..b82aaeeab94bc 100644 --- a/crates/ruff_python_index/Cargo.toml +++ b/crates/ruff_python_index/Cargo.toml @@ -22,5 +22,4 @@ ruff_text_size = { path = "../ruff_text_size" } itertools = { workspace = true } - [dev-dependencies] diff --git a/crates/ruff_python_index/src/indexer.rs b/crates/ruff_python_index/src/indexer.rs index 222e58fca0a2f..536661d04d03e 100644 --- a/crates/ruff_python_index/src/indexer.rs +++ b/crates/ruff_python_index/src/indexer.rs @@ -39,7 +39,7 @@ impl Indexer { let mut line_start = TextSize::default(); for (tok, range) in tokens.iter().flatten() { - let trivia = &locator.contents()[TextRange::new(prev_end, range.start())]; + let trivia = locator.slice(TextRange::new(prev_end, range.start())); // Get the trivia between the previous and the current token and detect any newlines. // This is necessary because `RustPython` doesn't emit `[Tok::Newline]` tokens @@ -99,18 +99,6 @@ impl Indexer { &self.comment_ranges } - /// Returns the comments in the given range as source code slices - pub fn comments_in_range<'a>( - &'a self, - range: TextRange, - locator: &'a Locator, - ) -> impl Iterator { - self.comment_ranges - .comments_in_range(range) - .iter() - .map(move |comment_range| locator.slice(*comment_range)) - } - /// Returns the line start positions of continuations (backslash). pub fn continuation_line_starts(&self) -> &[TextSize] { &self.continuation_lines @@ -262,14 +250,26 @@ impl Indexer { Some(continuation) } - /// Return `true` if a `Stmt` appears to be part of a multi-statement line, with - /// other statements preceding it. + /// Return `true` if a [`Stmt`] appears to be preceded by other statements in a multi-statement + /// line. pub fn preceded_by_multi_statement_line(&self, stmt: &Stmt, locator: &Locator) -> bool { has_leading_content(stmt.start(), locator) || self .preceded_by_continuations(stmt.start(), locator) .is_some() } + + /// Return `true` if a [`Stmt`] appears to be followed by other statements in a multi-statement + /// line. + pub fn followed_by_multi_statement_line(&self, stmt: &Stmt, locator: &Locator) -> bool { + has_trailing_content(stmt.end(), locator) + } + + /// Return `true` if a [`Stmt`] appears to be part of a multi-statement line. + pub fn in_multi_statement_line(&self, stmt: &Stmt, locator: &Locator) -> bool { + self.followed_by_multi_statement_line(stmt, locator) + || self.preceded_by_multi_statement_line(stmt, locator) + } } #[cfg(test)] diff --git a/crates/ruff_python_literal/Cargo.toml b/crates/ruff_python_literal/Cargo.toml index 819dd59149093..fd6a8dc439347 100644 --- a/crates/ruff_python_literal/Cargo.toml +++ b/crates/ruff_python_literal/Cargo.toml @@ -17,7 +17,6 @@ hexf-parse = "0.2.1" is-macro.workspace = true itertools = { workspace = true } lexical-parse-float = { version = "0.8.0", features = ["format"] } -num-bigint = { workspace = true } num-traits = { workspace = true } unic-ucd-category = "0.9" diff --git a/crates/ruff_python_literal/src/cformat.rs b/crates/ruff_python_literal/src/cformat.rs index f0aa883bdcd80..e635faa3845ba 100644 --- a/crates/ruff_python_literal/src/cformat.rs +++ b/crates/ruff_python_literal/src/cformat.rs @@ -1,15 +1,13 @@ //! Implementation of Printf-Style string formatting //! as per the [Python Docs](https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting). use bitflags::bitflags; -use num_traits::Signed; use std::{ - cmp, fmt, + fmt, iter::{Enumerate, Peekable}, str::FromStr, }; -use crate::{float, Case}; -use num_bigint::{BigInt, Sign}; +use crate::Case; #[derive(Debug, PartialEq)] pub enum CFormatErrorType { @@ -165,249 +163,6 @@ impl CFormatSpec { format_char, }) } - - fn compute_fill_string(fill_char: char, fill_chars_needed: usize) -> String { - (0..fill_chars_needed) - .map(|_| fill_char) - .collect::() - } - - fn fill_string( - &self, - string: String, - fill_char: char, - num_prefix_chars: Option, - ) -> String { - let mut num_chars = string.chars().count(); - if let Some(num_prefix_chars) = num_prefix_chars { - num_chars += num_prefix_chars; - } - let num_chars = num_chars; - - let width = match &self.min_field_width { - Some(CFormatQuantity::Amount(width)) => cmp::max(width, &num_chars), - _ => &num_chars, - }; - let fill_chars_needed = width.saturating_sub(num_chars); - let fill_string = CFormatSpec::compute_fill_string(fill_char, fill_chars_needed); - - if fill_string.is_empty() { - string - } else { - if self.flags.contains(CConversionFlags::LEFT_ADJUST) { - format!("{string}{fill_string}") - } else { - format!("{fill_string}{string}") - } - } - } - - fn fill_string_with_precision(&self, string: String, fill_char: char) -> String { - let num_chars = string.chars().count(); - - let width = match &self.precision { - Some(CFormatPrecision::Quantity(CFormatQuantity::Amount(width))) => { - cmp::max(width, &num_chars) - } - _ => &num_chars, - }; - let fill_chars_needed = width.saturating_sub(num_chars); - let fill_string = CFormatSpec::compute_fill_string(fill_char, fill_chars_needed); - - if fill_string.is_empty() { - string - } else { - // Don't left-adjust if precision-filling: that will always be prepending 0s to %d - // arguments, the LEFT_ADJUST flag will be used by a later call to fill_string with - // the 0-filled string as the string param. - format!("{fill_string}{string}") - } - } - - fn format_string_with_precision( - &self, - string: String, - precision: Option<&CFormatPrecision>, - ) -> String { - // truncate if needed - let string = match precision { - Some(CFormatPrecision::Quantity(CFormatQuantity::Amount(precision))) - if string.chars().count() > *precision => - { - string.chars().take(*precision).collect::() - } - Some(CFormatPrecision::Dot) => { - // truncate to 0 - String::new() - } - _ => string, - }; - self.fill_string(string, ' ', None) - } - - #[inline] - pub fn format_string(&self, string: String) -> String { - self.format_string_with_precision(string, self.precision.as_ref()) - } - - #[inline] - pub fn format_char(&self, ch: char) -> String { - self.format_string_with_precision( - ch.to_string(), - Some(&(CFormatQuantity::Amount(1).into())), - ) - } - - pub fn format_bytes(&self, bytes: &[u8]) -> Vec { - let bytes = if let Some(CFormatPrecision::Quantity(CFormatQuantity::Amount(precision))) = - self.precision - { - &bytes[..cmp::min(bytes.len(), precision)] - } else { - bytes - }; - if let Some(CFormatQuantity::Amount(width)) = self.min_field_width { - let fill = cmp::max(0, width - bytes.len()); - let mut v = Vec::with_capacity(bytes.len() + fill); - if self.flags.contains(CConversionFlags::LEFT_ADJUST) { - v.extend_from_slice(bytes); - v.append(&mut vec![b' '; fill]); - } else { - v.append(&mut vec![b' '; fill]); - v.extend_from_slice(bytes); - } - v - } else { - bytes.to_vec() - } - } - - pub fn format_number(&self, num: &BigInt) -> String { - use CNumberType::{Decimal, Hex, Octal}; - let magnitude = num.abs(); - let prefix = if self.flags.contains(CConversionFlags::ALTERNATE_FORM) { - match self.format_type { - CFormatType::Number(Octal) => "0o", - CFormatType::Number(Hex(Case::Lower)) => "0x", - CFormatType::Number(Hex(Case::Upper)) => "0X", - _ => "", - } - } else { - "" - }; - - let magnitude_string: String = match self.format_type { - CFormatType::Number(Decimal) => magnitude.to_str_radix(10), - CFormatType::Number(Octal) => magnitude.to_str_radix(8), - CFormatType::Number(Hex(Case::Lower)) => magnitude.to_str_radix(16), - CFormatType::Number(Hex(Case::Upper)) => { - let mut result = magnitude.to_str_radix(16); - result.make_ascii_uppercase(); - result - } - _ => unreachable!(), // Should not happen because caller has to make sure that this is a number - }; - - let sign_string = match num.sign() { - Sign::Minus => "-", - _ => self.flags.sign_string(), - }; - - let padded_magnitude_string = self.fill_string_with_precision(magnitude_string, '0'); - - if self.flags.contains(CConversionFlags::ZERO_PAD) { - let fill_char = if self.flags.contains(CConversionFlags::LEFT_ADJUST) { - ' ' // '-' overrides the '0' conversion if both are given - } else { - '0' - }; - let signed_prefix = format!("{sign_string}{prefix}"); - format!( - "{}{}", - signed_prefix, - self.fill_string( - padded_magnitude_string, - fill_char, - Some(signed_prefix.chars().count()), - ), - ) - } else { - self.fill_string( - format!("{sign_string}{prefix}{padded_magnitude_string}"), - ' ', - None, - ) - } - } - - pub fn format_float(&self, num: f64) -> String { - let sign_string = if num.is_sign_negative() && !num.is_nan() { - "-" - } else { - self.flags.sign_string() - }; - - let precision = match &self.precision { - Some(CFormatPrecision::Quantity(quantity)) => match quantity { - CFormatQuantity::Amount(amount) => *amount, - CFormatQuantity::FromValuesTuple => 6, - }, - Some(CFormatPrecision::Dot) => 0, - None => 6, - }; - - let magnitude_string = match &self.format_type { - CFormatType::Float(CFloatType::PointDecimal(case)) => { - let magnitude = num.abs(); - float::format_fixed( - precision, - magnitude, - *case, - self.flags.contains(CConversionFlags::ALTERNATE_FORM), - ) - } - CFormatType::Float(CFloatType::Exponent(case)) => { - let magnitude = num.abs(); - float::format_exponent( - precision, - magnitude, - *case, - self.flags.contains(CConversionFlags::ALTERNATE_FORM), - ) - } - CFormatType::Float(CFloatType::General(case)) => { - let precision = if precision == 0 { 1 } else { precision }; - let magnitude = num.abs(); - float::format_general( - precision, - magnitude, - *case, - self.flags.contains(CConversionFlags::ALTERNATE_FORM), - false, - ) - } - _ => unreachable!(), - }; - - if self.flags.contains(CConversionFlags::ZERO_PAD) { - let fill_char = if self.flags.contains(CConversionFlags::LEFT_ADJUST) { - ' ' - } else { - '0' - }; - format!( - "{}{}", - sign_string, - self.fill_string( - magnitude_string, - fill_char, - Some(sign_string.chars().count()), - ) - ) - } else { - self.fill_string(format!("{sign_string}{magnitude_string}"), ' ', None) - } - } } fn parse_spec_mapping_key(iter: &mut ParseIter) -> Result, ParsingError> @@ -741,38 +496,6 @@ impl CFormatString { mod tests { use super::*; - #[test] - fn test_fill_and_align() { - assert_eq!( - "%10s" - .parse::() - .unwrap() - .format_string("test".to_owned()), - " test".to_owned() - ); - assert_eq!( - "%-10s" - .parse::() - .unwrap() - .format_string("test".to_owned()), - "test ".to_owned() - ); - assert_eq!( - "%#10x" - .parse::() - .unwrap() - .format_number(&BigInt::from(0x1337)), - " 0x1337".to_owned() - ); - assert_eq!( - "%-#10x" - .parse::() - .unwrap() - .format_number(&BigInt::from(0x1337)), - "0x1337 ".to_owned() - ); - } - #[test] fn test_parse_key() { let expected = Ok(CFormatSpec { @@ -844,165 +567,6 @@ mod tests { }); let parsed = "% 0 -+++###10d".parse::(); assert_eq!(parsed, expected); - assert_eq!( - parsed.unwrap().format_number(&BigInt::from(12)), - "+12 ".to_owned() - ); - } - - #[test] - fn test_parse_and_format_string() { - assert_eq!( - "%5.4s" - .parse::() - .unwrap() - .format_string("Hello, World!".to_owned()), - " Hell".to_owned() - ); - assert_eq!( - "%-5.4s" - .parse::() - .unwrap() - .format_string("Hello, World!".to_owned()), - "Hell ".to_owned() - ); - assert_eq!( - "%.s" - .parse::() - .unwrap() - .format_string("Hello, World!".to_owned()), - String::new() - ); - assert_eq!( - "%5.s" - .parse::() - .unwrap() - .format_string("Hello, World!".to_owned()), - " ".to_owned() - ); - } - - #[test] - fn test_parse_and_format_unicode_string() { - assert_eq!( - "%.2s" - .parse::() - .unwrap() - .format_string("❤❤❤❤❤❤❤❤".to_owned()), - "❤❤".to_owned() - ); - } - - #[test] - fn test_parse_and_format_number() { - assert_eq!( - "%5d" - .parse::() - .unwrap() - .format_number(&BigInt::from(27)), - " 27".to_owned() - ); - assert_eq!( - "%05d" - .parse::() - .unwrap() - .format_number(&BigInt::from(27)), - "00027".to_owned() - ); - assert_eq!( - "%.5d" - .parse::() - .unwrap() - .format_number(&BigInt::from(27)), - "00027".to_owned() - ); - assert_eq!( - "%+05d" - .parse::() - .unwrap() - .format_number(&BigInt::from(27)), - "+0027".to_owned() - ); - assert_eq!( - "%-d" - .parse::() - .unwrap() - .format_number(&BigInt::from(-27)), - "-27".to_owned() - ); - assert_eq!( - "% d" - .parse::() - .unwrap() - .format_number(&BigInt::from(27)), - " 27".to_owned() - ); - assert_eq!( - "% d" - .parse::() - .unwrap() - .format_number(&BigInt::from(-27)), - "-27".to_owned() - ); - assert_eq!( - "%08x" - .parse::() - .unwrap() - .format_number(&BigInt::from(0x1337)), - "00001337".to_owned() - ); - assert_eq!( - "%#010x" - .parse::() - .unwrap() - .format_number(&BigInt::from(0x1337)), - "0x00001337".to_owned() - ); - assert_eq!( - "%-#010x" - .parse::() - .unwrap() - .format_number(&BigInt::from(0x1337)), - "0x1337 ".to_owned() - ); - } - - #[test] - fn test_parse_and_format_float() { - assert_eq!( - "%f".parse::().unwrap().format_float(1.2345), - "1.234500" - ); - assert_eq!( - "%.2f".parse::().unwrap().format_float(1.2345), - "1.23" - ); - assert_eq!( - "%.f".parse::().unwrap().format_float(1.2345), - "1" - ); - assert_eq!( - "%+.f".parse::().unwrap().format_float(1.2345), - "+1" - ); - assert_eq!( - "%+f".parse::().unwrap().format_float(1.2345), - "+1.234500" - ); - assert_eq!( - "% f".parse::().unwrap().format_float(1.2345), - " 1.234500" - ); - assert_eq!( - "%f".parse::().unwrap().format_float(-1.2345), - "-1.234500" - ); - assert_eq!( - "%f".parse::() - .unwrap() - .format_float(1.234_567_890_1), - "1.234568" - ); } #[test] diff --git a/crates/ruff_python_literal/src/escape.rs b/crates/ruff_python_literal/src/escape.rs index c291e13034d97..01de325f102d7 100644 --- a/crates/ruff_python_literal/src/escape.rs +++ b/crates/ruff_python_literal/src/escape.rs @@ -341,7 +341,7 @@ impl AsciiEscape<'_> { let mut single_count = 0; let mut double_count = 0; - for ch in source.iter() { + for ch in source { let incr = match ch { b'\'' => { single_count += 1; @@ -425,7 +425,7 @@ impl<'a> Escape for AsciiEscape<'a> { #[cold] fn write_body_slow(&self, formatter: &mut impl std::fmt::Write) -> std::fmt::Result { - for ch in self.source.iter() { + for ch in self.source { Self::write_char(*ch, self.layout().quote, formatter)?; } Ok(()) diff --git a/crates/ruff_python_literal/src/float.rs b/crates/ruff_python_literal/src/float.rs index 2a9b021f87c38..763d652445cc1 100644 --- a/crates/ruff_python_literal/src/float.rs +++ b/crates/ruff_python_literal/src/float.rs @@ -15,10 +15,10 @@ fn trim_slice(v: &[T], mut trim: impl FnMut(&T) -> bool) -> &[T] { // it.take_while_ref(&mut trim).for_each(drop); // hmm.. `&mut slice::Iter<_>` is not `Clone` // it.by_ref().rev().take_while_ref(&mut trim).for_each(drop); - while it.clone().next().map_or(false, &mut trim) { + while it.clone().next().is_some_and(&mut trim) { it.next(); } - while it.clone().next_back().map_or(false, &mut trim) { + while it.clone().next_back().is_some_and(&mut trim) { it.next_back(); } it.as_slice() diff --git a/crates/ruff_python_literal/src/format.rs b/crates/ruff_python_literal/src/format.rs index 7d3625b4db332..01f98587634c9 100644 --- a/crates/ruff_python_literal/src/format.rs +++ b/crates/ruff_python_literal/src/format.rs @@ -1,11 +1,9 @@ use itertools::{Itertools, PeekingNext}; -use num_traits::{cast::ToPrimitive, FromPrimitive, Signed}; -use std::ops::Deref; -use std::{cmp, str::FromStr}; +use std::error::Error; +use std::str::FromStr; -use crate::{float, Case}; -use num_bigint::{BigInt, Sign}; +use crate::Case; trait FormatParse { fn parse(text: &str) -> (Option, &str) @@ -179,24 +177,82 @@ impl FormatParse for FormatType { Some('g') => (Some(Self::GeneralFormat(Case::Lower)), chars.as_str()), Some('G') => (Some(Self::GeneralFormat(Case::Upper)), chars.as_str()), Some('%') => (Some(Self::Percentage), chars.as_str()), + Some(_) => (None, chars.as_str()), _ => (None, text), } } } +/// The format specification component of a format field +/// +/// For example the content would be parsed from `<20` in: +/// ```python +/// "hello {name:<20}".format(name="test") +/// ``` +/// +/// Format specifications allow nested placeholders for dynamic formatting. +/// For example, the following statements are equivalent: +/// ```python +/// "hello {name:{fmt}}".format(name="test", fmt="<20") +/// "hello {name:{align}{width}}".format(name="test", align="<", width="20") +/// "hello {name:<20{empty}>}".format(name="test", empty="") +/// ``` +/// +/// Nested placeholders can include additional format specifiers. +/// ```python +/// "hello {name:{fmt:*>}}".format(name="test", fmt="<20") +/// ``` +/// +/// However, placeholders can only be singly nested (preserving our sanity). +/// A [`FormatSpecError::PlaceholderRecursionExceeded`] will be raised while parsing in this case. +/// ```python +/// "hello {name:{fmt:{not_allowed}}}".format(name="test", fmt="<20") # Syntax error +/// ``` +/// +/// When placeholders are present in a format specification, parsing will return a [`DynamicFormatSpec`] +/// and avoid attempting to parse any of the clauses. Otherwise, a [`StaticFormatSpec`] will be used. #[derive(Debug, PartialEq)] -pub struct FormatSpec { +pub enum FormatSpec { + Static(StaticFormatSpec), + Dynamic(DynamicFormatSpec), +} + +#[derive(Debug, PartialEq)] +pub struct StaticFormatSpec { + // Ex) `!s` in `'{!s}'` conversion: Option, + // Ex) `*` in `'{:*^30}'` fill: Option, + // Ex) `<` in `'{:<30}'` align: Option, + // Ex) `+` in `'{:+f}'` sign: Option, + // Ex) `#` in `'{:#x}'` alternate_form: bool, + // Ex) `30` in `'{:<30}'` width: Option, + // Ex) `,` in `'{:,}'` grouping_option: Option, + // Ex) `2` in `'{:.2}'` precision: Option, + // Ex) `f` in `'{:+f}'` format_type: Option, } +#[derive(Debug, PartialEq)] +pub struct DynamicFormatSpec { + // Ex) `x` and `y` in `'{:*{x},{y}b}'` + pub placeholders: Vec, +} + +#[derive(Copy, Clone, Debug, PartialEq, Default)] +pub enum AllowPlaceholderNesting { + #[default] + Yes, + No, + AllowPlaceholderNesting, +} + fn get_num_digits(text: &str) -> usize { for (index, character) in text.char_indices() { if !character.is_ascii_digit() { @@ -271,9 +327,38 @@ fn parse_precision(text: &str) -> Result<(Option, &str), FormatSpecError> }) } +/// Parses a placeholder format part within a format specification +fn parse_nested_placeholder(text: &str) -> Result, FormatSpecError> { + match FormatString::parse_spec(text, AllowPlaceholderNesting::No) { + // Not a nested placeholder, OK + Err(FormatParseError::MissingStartBracket) => Ok(None), + Err(err) => Err(FormatSpecError::InvalidPlaceholder(err)), + Ok((format_part, text)) => Ok(Some((format_part, text))), + } +} + +/// Parse all placeholders in a format specification +/// If no placeholders are present, an empty vector will be returned +fn parse_nested_placeholders(mut text: &str) -> Result, FormatSpecError> { + let mut placeholders = vec![]; + while let Some(bracket) = text.find('{') { + if let Some((format_part, rest)) = parse_nested_placeholder(&text[bracket..])? { + text = rest; + placeholders.push(format_part); + } else { + text = &text[bracket + 1..]; + } + } + Ok(placeholders) +} + impl FormatSpec { pub fn parse(text: &str) -> Result { - // get_integer in CPython + let placeholders = parse_nested_placeholders(text)?; + if !placeholders.is_empty() { + return Ok(FormatSpec::Dynamic(DynamicFormatSpec { placeholders })); + } + let (conversion, text) = FormatConversion::parse(text); let (mut fill, mut align, text) = parse_fill_and_align(text); let (sign, text) = FormatSign::parse(text); @@ -282,17 +367,28 @@ impl FormatSpec { let (width, text) = parse_number(text)?; let (grouping_option, text) = FormatGrouping::parse(text); let (precision, text) = parse_precision(text)?; - let (format_type, text) = FormatType::parse(text); - if !text.is_empty() { - return Err(FormatSpecError::InvalidFormatSpecifier); - } + + let (format_type, _text) = if text.is_empty() { + (None, text) + } else { + // If there's any remaining text, we should yield a valid format type and consume it + // all. + let (format_type, text) = FormatType::parse(text); + if format_type.is_none() { + return Err(FormatSpecError::InvalidFormatType); + } + if !text.is_empty() { + return Err(FormatSpecError::InvalidFormatSpecifier); + } + (format_type, text) + }; if zero && fill.is_none() { fill.replace('0'); align = align.or(Some(FormatAlign::AfterSign)); } - Ok(FormatSpec { + Ok(FormatSpec::Static(StaticFormatSpec { conversion, fill, align, @@ -302,419 +398,7 @@ impl FormatSpec { grouping_option, precision, format_type, - }) - } - - fn compute_fill_string(fill_char: char, fill_chars_needed: i32) -> String { - (0..fill_chars_needed) - .map(|_| fill_char) - .collect::() - } - - #[allow( - clippy::cast_possible_wrap, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - fn add_magnitude_separators_for_char( - magnitude_str: &str, - inter: i32, - sep: char, - disp_digit_cnt: i32, - ) -> String { - // Don't add separators to the floating decimal point of numbers - let mut parts = magnitude_str.splitn(2, '.'); - let magnitude_int_str = parts.next().unwrap().to_string(); - let dec_digit_cnt = magnitude_str.len() as i32 - magnitude_int_str.len() as i32; - let int_digit_cnt = disp_digit_cnt - dec_digit_cnt; - let mut result = FormatSpec::separate_integer(magnitude_int_str, inter, sep, int_digit_cnt); - if let Some(part) = parts.next() { - result.push_str(&format!(".{part}")); - } - result - } - - #[allow( - clippy::cast_sign_loss, - clippy::cast_possible_wrap, - clippy::cast_possible_truncation - )] - fn separate_integer( - magnitude_str: String, - inter: i32, - sep: char, - disp_digit_cnt: i32, - ) -> String { - let magnitude_len = magnitude_str.len() as i32; - let offset = i32::from(disp_digit_cnt % (inter + 1) == 0); - let disp_digit_cnt = disp_digit_cnt + offset; - let pad_cnt = disp_digit_cnt - magnitude_len; - let sep_cnt = disp_digit_cnt / (inter + 1); - let diff = pad_cnt - sep_cnt; - if pad_cnt > 0 && diff > 0 { - // separate with 0 padding - let padding = "0".repeat(diff as usize); - let padded_num = format!("{padding}{magnitude_str}"); - FormatSpec::insert_separator(padded_num, inter, sep, sep_cnt) - } else { - // separate without padding - let sep_cnt = (magnitude_len - 1) / inter; - FormatSpec::insert_separator(magnitude_str, inter, sep, sep_cnt) - } - } - - #[allow( - clippy::cast_sign_loss, - clippy::cast_possible_truncation, - clippy::cast_possible_wrap - )] - fn insert_separator(mut magnitude_str: String, inter: i32, sep: char, sep_cnt: i32) -> String { - let magnitude_len = magnitude_str.len() as i32; - for i in 1..=sep_cnt { - magnitude_str.insert((magnitude_len - inter * i) as usize, sep); - } - magnitude_str - } - - fn validate_format(&self, default_format_type: FormatType) -> Result<(), FormatSpecError> { - let format_type = self.format_type.as_ref().unwrap_or(&default_format_type); - match (&self.grouping_option, format_type) { - ( - Some(FormatGrouping::Comma), - FormatType::String - | FormatType::Character - | FormatType::Binary - | FormatType::Octal - | FormatType::Hex(_) - | FormatType::Number(_), - ) => { - let ch = char::from(format_type); - Err(FormatSpecError::UnspecifiedFormat(',', ch)) - } - ( - Some(FormatGrouping::Underscore), - FormatType::String | FormatType::Character | FormatType::Number(_), - ) => { - let ch = char::from(format_type); - Err(FormatSpecError::UnspecifiedFormat('_', ch)) - } - _ => Ok(()), - } - } - - fn get_separator_interval(&self) -> usize { - match self.format_type { - Some(FormatType::Binary | FormatType::Octal | FormatType::Hex(_)) => 4, - Some(FormatType::Decimal | FormatType::Number(_) | FormatType::FixedPoint(_)) => 3, - None => 3, - _ => panic!("Separators only valid for numbers!"), - } - } - - #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] - fn add_magnitude_separators(&self, magnitude_str: String, prefix: &str) -> String { - match &self.grouping_option { - Some(fg) => { - let sep = match fg { - FormatGrouping::Comma => ',', - FormatGrouping::Underscore => '_', - }; - let inter = self.get_separator_interval().try_into().unwrap(); - let magnitude_len = magnitude_str.len(); - let width = self.width.unwrap_or(magnitude_len) as i32 - prefix.len() as i32; - let disp_digit_cnt = cmp::max(width, magnitude_len as i32); - FormatSpec::add_magnitude_separators_for_char( - &magnitude_str, - inter, - sep, - disp_digit_cnt, - ) - } - None => magnitude_str, - } - } - - pub fn format_bool(&self, input: bool) -> Result { - let x = u8::from(input); - match &self.format_type { - Some( - FormatType::Binary - | FormatType::Decimal - | FormatType::Octal - | FormatType::Number(Case::Lower) - | FormatType::Hex(_) - | FormatType::GeneralFormat(_) - | FormatType::Character, - ) => self.format_int(&BigInt::from_u8(x).unwrap()), - Some(FormatType::Exponent(_) | FormatType::FixedPoint(_) | FormatType::Percentage) => { - self.format_float(f64::from(x)) - } - None => { - let first_letter = (input.to_string().as_bytes()[0] as char).to_uppercase(); - Ok(first_letter.collect::() + &input.to_string()[1..]) - } - _ => Err(FormatSpecError::InvalidFormatSpecifier), - } - } - - pub fn format_float(&self, num: f64) -> Result { - self.validate_format(FormatType::FixedPoint(Case::Lower))?; - let precision = self.precision.unwrap_or(6); - let magnitude = num.abs(); - let raw_magnitude_str: Result = match &self.format_type { - Some(FormatType::FixedPoint(case)) => Ok(float::format_fixed( - precision, - magnitude, - *case, - self.alternate_form, - )), - Some( - FormatType::Decimal - | FormatType::Binary - | FormatType::Octal - | FormatType::Hex(_) - | FormatType::String - | FormatType::Character - | FormatType::Number(Case::Upper), - ) => { - let ch = char::from(self.format_type.as_ref().unwrap()); - Err(FormatSpecError::UnknownFormatCode(ch, "float")) - } - Some(FormatType::GeneralFormat(case) | FormatType::Number(case)) => { - let precision = if precision == 0 { 1 } else { precision }; - Ok(float::format_general( - precision, - magnitude, - *case, - self.alternate_form, - false, - )) - } - Some(FormatType::Exponent(case)) => Ok(float::format_exponent( - precision, - magnitude, - *case, - self.alternate_form, - )), - Some(FormatType::Percentage) => match magnitude { - magnitude if magnitude.is_nan() => Ok("nan%".to_owned()), - magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()), - _ => { - let result = format!("{:.*}", precision, magnitude * 100.0); - let point = float::decimal_point_or_empty(precision, self.alternate_form); - Ok(format!("{result}{point}%")) - } - }, - None => match magnitude { - magnitude if magnitude.is_nan() => Ok("nan".to_owned()), - magnitude if magnitude.is_infinite() => Ok("inf".to_owned()), - _ => match self.precision { - Some(precision) => Ok(float::format_general( - precision, - magnitude, - Case::Lower, - self.alternate_form, - true, - )), - None => Ok(float::to_string(magnitude)), - }, - }, - }; - let format_sign = self.sign.unwrap_or(FormatSign::Minus); - let sign_str = if num.is_sign_negative() && !num.is_nan() { - "-" - } else { - match format_sign { - FormatSign::Plus => "+", - FormatSign::Minus => "", - FormatSign::MinusOrSpace => " ", - } - }; - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str); - Ok( - self.format_sign_and_align( - &AsciiStr::new(&magnitude_str), - sign_str, - FormatAlign::Right, - ), - ) - } - - #[inline] - fn format_int_radix(&self, magnitude: &BigInt, radix: u32) -> Result { - match self.precision { - Some(_) => Err(FormatSpecError::PrecisionNotAllowed), - None => Ok(magnitude.to_str_radix(radix)), - } - } - - pub fn format_int(&self, num: &BigInt) -> Result { - self.validate_format(FormatType::Decimal)?; - let magnitude = num.abs(); - let prefix = if self.alternate_form { - match self.format_type { - Some(FormatType::Binary) => "0b", - Some(FormatType::Octal) => "0o", - Some(FormatType::Hex(Case::Lower)) => "0x", - Some(FormatType::Hex(Case::Upper)) => "0X", - _ => "", - } - } else { - "" - }; - let raw_magnitude_str = match self.format_type { - Some(FormatType::Binary) => self.format_int_radix(&magnitude, 2), - Some(FormatType::Decimal) => self.format_int_radix(&magnitude, 10), - Some(FormatType::Octal) => self.format_int_radix(&magnitude, 8), - Some(FormatType::Hex(Case::Lower)) => self.format_int_radix(&magnitude, 16), - Some(FormatType::Hex(Case::Upper)) => { - if self.precision.is_some() { - Err(FormatSpecError::PrecisionNotAllowed) - } else { - let mut result = magnitude.to_str_radix(16); - result.make_ascii_uppercase(); - Ok(result) - } - } - - Some(FormatType::Number(Case::Lower)) => self.format_int_radix(&magnitude, 10), - Some(FormatType::Number(Case::Upper)) => { - Err(FormatSpecError::UnknownFormatCode('N', "int")) - } - Some(FormatType::String) => Err(FormatSpecError::UnknownFormatCode('s', "int")), - Some(FormatType::Character) => match (self.sign, self.alternate_form) { - (Some(_), _) => Err(FormatSpecError::NotAllowed("Sign")), - (_, true) => Err(FormatSpecError::NotAllowed("Alternate form (#)")), - (_, _) => match num.to_u32() { - Some(n) if n <= 0x0010_ffff => Ok(std::char::from_u32(n).unwrap().to_string()), - Some(_) | None => Err(FormatSpecError::CodeNotInRange), - }, - }, - Some( - FormatType::GeneralFormat(_) - | FormatType::FixedPoint(_) - | FormatType::Exponent(_) - | FormatType::Percentage, - ) => match num.to_f64() { - Some(float) => return self.format_float(float), - _ => Err(FormatSpecError::UnableToConvert), - }, - None => self.format_int_radix(&magnitude, 10), - }?; - let format_sign = self.sign.unwrap_or(FormatSign::Minus); - let sign_str = match num.sign() { - Sign::Minus => "-", - _ => match format_sign { - FormatSign::Plus => "+", - FormatSign::Minus => "", - FormatSign::MinusOrSpace => " ", - }, - }; - let sign_prefix = format!("{sign_str}{prefix}"); - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str, &sign_prefix); - Ok(self.format_sign_and_align( - &AsciiStr::new(&magnitude_str), - &sign_prefix, - FormatAlign::Right, - )) - } - - pub fn format_string(&self, s: &T) -> Result - where - T: CharLen + Deref, - { - self.validate_format(FormatType::String)?; - match self.format_type { - Some(FormatType::String) | None => { - let mut value = self.format_sign_and_align(s, "", FormatAlign::Left); - if let Some(precision) = self.precision { - value.truncate(precision); - } - Ok(value) - } - _ => { - let ch = char::from(self.format_type.as_ref().unwrap()); - Err(FormatSpecError::UnknownFormatCode(ch, "str")) - } - } - } - - #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] - fn format_sign_and_align( - &self, - magnitude_str: &T, - sign_str: &str, - default_align: FormatAlign, - ) -> String - where - T: CharLen + Deref, - { - let align = self.align.unwrap_or(default_align); - - let num_chars = magnitude_str.char_len(); - let fill_char = self.fill.unwrap_or(' '); - let fill_chars_needed: i32 = self.width.map_or(0, |w| { - cmp::max(0, (w as i32) - (num_chars as i32) - (sign_str.len() as i32)) - }); - - let magnitude_str = &**magnitude_str; - match align { - FormatAlign::Left => format!( - "{}{}{}", - sign_str, - magnitude_str, - FormatSpec::compute_fill_string(fill_char, fill_chars_needed) - ), - FormatAlign::Right => format!( - "{}{}{}", - FormatSpec::compute_fill_string(fill_char, fill_chars_needed), - sign_str, - magnitude_str - ), - FormatAlign::AfterSign => format!( - "{}{}{}", - sign_str, - FormatSpec::compute_fill_string(fill_char, fill_chars_needed), - magnitude_str - ), - FormatAlign::Center => { - let left_fill_chars_needed = fill_chars_needed / 2; - let right_fill_chars_needed = fill_chars_needed - left_fill_chars_needed; - let left_fill_string = - FormatSpec::compute_fill_string(fill_char, left_fill_chars_needed); - let right_fill_string = - FormatSpec::compute_fill_string(fill_char, right_fill_chars_needed); - format!("{left_fill_string}{sign_str}{magnitude_str}{right_fill_string}") - } - } - } -} - -pub trait CharLen { - /// Returns the number of characters in the text - fn char_len(&self) -> usize; -} - -struct AsciiStr<'a> { - inner: &'a str, -} - -impl<'a> AsciiStr<'a> { - fn new(inner: &'a str) -> Self { - Self { inner } - } -} - -impl CharLen for AsciiStr<'_> { - fn char_len(&self) -> usize { - self.inner.len() - } -} - -impl Deref for AsciiStr<'_> { - type Target = str; - fn deref(&self) -> &Self::Target { - self.inner + })) } } @@ -723,6 +407,9 @@ pub enum FormatSpecError { DecimalDigitsTooMany, PrecisionTooBig, InvalidFormatSpecifier, + InvalidFormatType, + InvalidPlaceholder(FormatParseError), + PlaceholderRecursionExceeded, UnspecifiedFormat(char, char), UnknownFormatCode(char, &'static str), PrecisionNotAllowed, @@ -737,13 +424,46 @@ pub enum FormatParseError { UnmatchedBracket, MissingStartBracket, UnescapedStartBracketInLiteral, - InvalidFormatSpecifier, + PlaceholderRecursionExceeded, UnknownConversion, EmptyAttribute, MissingRightBracket, InvalidCharacterAfterRightBracket, } +impl std::fmt::Display for FormatParseError { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnmatchedBracket => { + std::write!(fmt, "unmatched bracket in format string") + } + Self::MissingStartBracket => { + std::write!(fmt, "missing start bracket in format string") + } + Self::UnescapedStartBracketInLiteral => { + std::write!(fmt, "unescaped start bracket in literal") + } + Self::PlaceholderRecursionExceeded => { + std::write!(fmt, "multiply nested placeholder not allowed") + } + Self::UnknownConversion => { + std::write!(fmt, "unknown conversion") + } + Self::EmptyAttribute => { + std::write!(fmt, "empty attribute") + } + Self::MissingRightBracket => { + std::write!(fmt, "missing right bracket") + } + Self::InvalidCharacterAfterRightBracket => { + std::write!(fmt, "invalid character after right bracket") + } + } + } +} + +impl Error for FormatParseError {} + impl FromStr for FormatSpec { type Err = FormatSpecError; fn from_str(s: &str) -> Result { @@ -924,20 +644,22 @@ impl FormatString { }) } - fn parse_spec(text: &str) -> Result<(FormatPart, &str), FormatParseError> { + fn parse_spec( + text: &str, + allow_nesting: AllowPlaceholderNesting, + ) -> Result<(FormatPart, &str), FormatParseError> { + let Some(text) = text.strip_prefix('{') else { + return Err(FormatParseError::MissingStartBracket); + }; + let mut nested = false; - let mut end_bracket_pos = None; let mut left = String::new(); - // There may be one layer nesting brackets in spec for (idx, c) in text.char_indices() { - if idx == 0 { - if c != '{' { - return Err(FormatParseError::MissingStartBracket); - } - } else if c == '{' { - if nested { - return Err(FormatParseError::InvalidFormatSpecifier); + if c == '{' { + // There may be one layer nesting brackets in spec + if nested || allow_nesting == AllowPlaceholderNesting::No { + return Err(FormatParseError::PlaceholderRecursionExceeded); } nested = true; left.push(c); @@ -948,19 +670,13 @@ impl FormatString { left.push(c); continue; } - end_bracket_pos = Some(idx); - break; - } else { - left.push(c); + let (_, right) = text.split_at(idx + 1); + let format_part = FormatString::parse_part_in_brackets(&left)?; + return Ok((format_part, right)); } + left.push(c); } - if let Some(pos) = end_bracket_pos { - let (_, right) = text.split_at(pos); - let format_part = FormatString::parse_part_in_brackets(&left)?; - Ok((format_part, &right[1..])) - } else { - Err(FormatParseError::UnmatchedBracket) - } + Err(FormatParseError::UnmatchedBracket) } } @@ -979,7 +695,7 @@ impl<'a> FromTemplate<'a> for FormatString { // Try to parse both literals and bracketed format parts until we // run out of text cur_text = FormatString::parse_literal(cur_text) - .or_else(|_| FormatString::parse_spec(cur_text)) + .or_else(|_| FormatString::parse_spec(cur_text, AllowPlaceholderNesting::Yes)) .map(|(part, new_text)| { parts.push(part); new_text @@ -1021,7 +737,7 @@ mod tests { #[test] fn test_width_only() { - let expected = Ok(FormatSpec { + let expected = Ok(FormatSpec::Static(StaticFormatSpec { conversion: None, fill: None, align: None, @@ -1031,13 +747,13 @@ mod tests { grouping_option: None, precision: None, format_type: None, - }); + })); assert_eq!(FormatSpec::parse("33"), expected); } #[test] fn test_fill_and_width() { - let expected = Ok(FormatSpec { + let expected = Ok(FormatSpec::Static(StaticFormatSpec { conversion: None, fill: Some('<'), align: Some(FormatAlign::Right), @@ -1047,13 +763,61 @@ mod tests { grouping_option: None, precision: None, format_type: None, - }); + })); assert_eq!(FormatSpec::parse("<>33"), expected); } + #[test] + fn test_format_part() { + let expected = Ok(FormatSpec::Dynamic(DynamicFormatSpec { + placeholders: vec![FormatPart::Field { + field_name: "x".to_string(), + conversion_spec: None, + format_spec: String::new(), + }], + })); + assert_eq!(FormatSpec::parse("{x}"), expected); + } + + #[test] + fn test_dynamic_format_spec() { + let expected = Ok(FormatSpec::Dynamic(DynamicFormatSpec { + placeholders: vec![ + FormatPart::Field { + field_name: "x".to_string(), + conversion_spec: None, + format_spec: String::new(), + }, + FormatPart::Field { + field_name: "y".to_string(), + conversion_spec: None, + format_spec: "<2".to_string(), + }, + FormatPart::Field { + field_name: "z".to_string(), + conversion_spec: None, + format_spec: String::new(), + }, + ], + })); + assert_eq!(FormatSpec::parse("{x}{y:<2}{z}"), expected); + } + + #[test] + fn test_dynamic_format_spec_with_others() { + let expected = Ok(FormatSpec::Dynamic(DynamicFormatSpec { + placeholders: vec![FormatPart::Field { + field_name: "x".to_string(), + conversion_spec: None, + format_spec: String::new(), + }], + })); + assert_eq!(FormatSpec::parse("<{x}20b"), expected); + } + #[test] fn test_all() { - let expected = Ok(FormatSpec { + let expected = Ok(FormatSpec::Static(StaticFormatSpec { conversion: None, fill: Some('<'), align: Some(FormatAlign::Right), @@ -1063,102 +827,10 @@ mod tests { grouping_option: Some(FormatGrouping::Comma), precision: Some(11), format_type: Some(FormatType::Binary), - }); + })); assert_eq!(FormatSpec::parse("<>-#23,.11b"), expected); } - fn format_bool(text: &str, value: bool) -> Result { - FormatSpec::parse(text).and_then(|spec| spec.format_bool(value)) - } - - #[test] - fn test_format_bool() { - assert_eq!(format_bool("b", true), Ok("1".to_owned())); - assert_eq!(format_bool("b", false), Ok("0".to_owned())); - assert_eq!(format_bool("d", true), Ok("1".to_owned())); - assert_eq!(format_bool("d", false), Ok("0".to_owned())); - assert_eq!(format_bool("o", true), Ok("1".to_owned())); - assert_eq!(format_bool("o", false), Ok("0".to_owned())); - assert_eq!(format_bool("n", true), Ok("1".to_owned())); - assert_eq!(format_bool("n", false), Ok("0".to_owned())); - assert_eq!(format_bool("x", true), Ok("1".to_owned())); - assert_eq!(format_bool("x", false), Ok("0".to_owned())); - assert_eq!(format_bool("X", true), Ok("1".to_owned())); - assert_eq!(format_bool("X", false), Ok("0".to_owned())); - assert_eq!(format_bool("g", true), Ok("1".to_owned())); - assert_eq!(format_bool("g", false), Ok("0".to_owned())); - assert_eq!(format_bool("G", true), Ok("1".to_owned())); - assert_eq!(format_bool("G", false), Ok("0".to_owned())); - assert_eq!(format_bool("c", true), Ok("\x01".to_owned())); - assert_eq!(format_bool("c", false), Ok("\x00".to_owned())); - assert_eq!(format_bool("e", true), Ok("1.000000e+00".to_owned())); - assert_eq!(format_bool("e", false), Ok("0.000000e+00".to_owned())); - assert_eq!(format_bool("E", true), Ok("1.000000E+00".to_owned())); - assert_eq!(format_bool("E", false), Ok("0.000000E+00".to_owned())); - assert_eq!(format_bool("f", true), Ok("1.000000".to_owned())); - assert_eq!(format_bool("f", false), Ok("0.000000".to_owned())); - assert_eq!(format_bool("F", true), Ok("1.000000".to_owned())); - assert_eq!(format_bool("F", false), Ok("0.000000".to_owned())); - assert_eq!(format_bool("%", true), Ok("100.000000%".to_owned())); - assert_eq!(format_bool("%", false), Ok("0.000000%".to_owned())); - } - - #[test] - fn test_format_int() { - assert_eq!( - FormatSpec::parse("d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("16".to_owned()) - ); - assert_eq!( - FormatSpec::parse("x") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("10".to_owned()) - ); - assert_eq!( - FormatSpec::parse("b") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("10000".to_owned()) - ); - assert_eq!( - FormatSpec::parse("o") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("20".to_owned()) - ); - assert_eq!( - FormatSpec::parse("+d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("+16".to_owned()) - ); - assert_eq!( - FormatSpec::parse("^ 5d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Minus, b"\x10")), - Ok(" -16 ".to_owned()) - ); - assert_eq!( - FormatSpec::parse("0>+#10x") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("00000+0x10".to_owned()) - ); - } - - #[test] - fn test_format_int_sep() { - let spec = FormatSpec::parse(",").expect(""); - assert_eq!(spec.grouping_option, Some(FormatGrouping::Comma)); - assert_eq!( - spec.format_int(&BigInt::from_str("1234567890123456789012345678").unwrap()), - Ok("1,234,567,890,123,456,789,012,345,678".to_owned()) - ); - } - #[test] fn test_format_parse() { let expected = Ok(FormatString { @@ -1181,6 +853,22 @@ mod tests { assert_eq!(FormatString::from_str("abcd{1}:{key}"), expected); } + #[test] + fn test_format_parse_nested_placeholder() { + let expected = Ok(FormatString { + format_parts: vec![ + FormatPart::Literal("abcd".to_owned()), + FormatPart::Field { + field_name: "1".to_owned(), + conversion_spec: None, + format_spec: "{a}".to_owned(), + }, + ], + }); + + assert_eq!(FormatString::from_str("abcd{1:{a}}"), expected); + } + #[test] fn test_format_parse_multi_byte_char() { assert!(FormatString::from_str("{a:%ЫйЯЧ}").is_ok()); @@ -1237,10 +925,48 @@ mod tests { FormatSpec::parse("o!"), Err(FormatSpecError::InvalidFormatSpecifier) ); + assert_eq!( + FormatSpec::parse("{"), + Err(FormatSpecError::InvalidPlaceholder( + FormatParseError::UnmatchedBracket + )) + ); + assert_eq!( + FormatSpec::parse("{x"), + Err(FormatSpecError::InvalidPlaceholder( + FormatParseError::UnmatchedBracket + )) + ); + assert_eq!( + FormatSpec::parse("}"), + Err(FormatSpecError::InvalidFormatType) + ); + assert_eq!( + FormatSpec::parse("{}}"), + // Note this should be an `InvalidFormatType` but we give up + // on all other parsing validation when we see a placeholder + Ok(FormatSpec::Dynamic(DynamicFormatSpec { + placeholders: vec![FormatPart::Field { + field_name: String::new(), + conversion_spec: None, + format_spec: String::new() + }] + })) + ); + assert_eq!( + FormatSpec::parse("{{x}}"), + Err(FormatSpecError::InvalidPlaceholder( + FormatParseError::PlaceholderRecursionExceeded + )) + ); assert_eq!( FormatSpec::parse("d "), Err(FormatSpecError::InvalidFormatSpecifier) ); + assert_eq!( + FormatSpec::parse("z"), + Err(FormatSpecError::InvalidFormatType) + ); } #[test] diff --git a/crates/ruff_python_parser/Cargo.toml b/crates/ruff_python_parser/Cargo.toml index 052105013a1f6..02b27577b2e66 100644 --- a/crates/ruff_python_parser/Cargo.toml +++ b/crates/ruff_python_parser/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" [lib] [dependencies] -ruff_python_ast = { path = "../ruff_python_ast"} +ruff_python_ast = { path = "../ruff_python_ast" } ruff_text_size = { path = "../ruff_text_size" } anyhow = { workspace = true } @@ -31,6 +31,7 @@ static_assertions = "1.1.0" [dev-dependencies] insta = { workspace = true } +test-case = { workspace = true } [build-dependencies] anyhow = { workspace = true } diff --git a/crates/ruff_python_parser/src/context.rs b/crates/ruff_python_parser/src/context.rs index 683c35a30ab3b..83aab32a1f246 100644 --- a/crates/ruff_python_parser/src/context.rs +++ b/crates/ruff_python_parser/src/context.rs @@ -49,132 +49,131 @@ pub(crate) fn set_context(expr: Expr, ctx: ExprContext) -> Expr { #[cfg(test)] mod tests { - use crate::Parse; - use ruff_python_ast as ast; + use crate::parser::parse_suite; #[test] fn test_assign_name() { let source = "x = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_tuple() { let source = "(x, y) = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_list() { let source = "[x, y] = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_attribute() { let source = "x.y = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_subscript() { let source = "x[y] = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_starred() { let source = "(x, *y) = (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_for() { let source = "for x in (1, 2, 3): pass"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_list_comp() { let source = "x = [y for y in (1, 2, 3)]"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_set_comp() { let source = "x = {y for y in (1, 2, 3)}"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_with() { let source = "with 1 as x: pass"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_assign_named_expr() { let source = "if x:= 1: pass"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_ann_assign_name() { let source = "x: int = 1"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_aug_assign_name() { let source = "x += 1"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_aug_assign_attribute() { let source = "x.y += (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_aug_assign_subscript() { let source = "x[y] += (1, 2, 3)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_del_name() { let source = "del x"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_del_attribute() { let source = "del x.y"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_del_subscript() { let source = "del x[y]"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } } diff --git a/crates/ruff_python_parser/src/function.rs b/crates/ruff_python_parser/src/function.rs index a26ef6395eea7..eeab6cfd5c71d 100644 --- a/crates/ruff_python_parser/src/function.rs +++ b/crates/ruff_python_parser/src/function.rs @@ -12,7 +12,7 @@ pub(crate) struct ArgumentList { } // Perform validation of function/lambda arguments in a function definition. -pub(crate) fn validate_arguments(arguments: &ast::Arguments) -> Result<(), LexicalError> { +pub(crate) fn validate_arguments(arguments: &ast::Parameters) -> Result<(), LexicalError> { let mut all_arg_names = FxHashSet::with_capacity_and_hasher( arguments.posonlyargs.len() + arguments.args.len() @@ -26,18 +26,18 @@ pub(crate) fn validate_arguments(arguments: &ast::Arguments) -> Result<(), Lexic let args = arguments.args.iter(); let kwonlyargs = arguments.kwonlyargs.iter(); - let vararg: Option<&ast::Arg> = arguments.vararg.as_deref(); - let kwarg: Option<&ast::Arg> = arguments.kwarg.as_deref(); + let vararg: Option<&ast::Parameter> = arguments.vararg.as_deref(); + let kwarg: Option<&ast::Parameter> = arguments.kwarg.as_deref(); for arg in posonlyargs .chain(args) .chain(kwonlyargs) - .map(|arg| &arg.def) + .map(|arg| &arg.parameter) .chain(vararg) .chain(kwarg) { let range = arg.range; - let arg_name = arg.arg.as_str(); + let arg_name = arg.name.as_str(); if !all_arg_names.insert(arg_name) { return Err(LexicalError { error: LexicalErrorType::DuplicateArgumentError(arg_name.to_string()), @@ -50,7 +50,10 @@ pub(crate) fn validate_arguments(arguments: &ast::Arguments) -> Result<(), Lexic } pub(crate) fn validate_pos_params( - args: &(Vec, Vec), + args: &( + Vec, + Vec, + ), ) -> Result<(), LexicalError> { let (posonlyargs, args) = args; #[allow(clippy::skip_while_next)] @@ -63,7 +66,7 @@ pub(crate) fn validate_pos_params( if let Some(invalid) = first_invalid { return Err(LexicalError { error: LexicalErrorType::DefaultArgumentError, - location: invalid.def.range.start(), + location: invalid.parameter.start(), }); } Ok(()) @@ -75,14 +78,18 @@ type FunctionArgument = ( ); // Parse arguments as supplied during a function/lambda *call*. -pub(crate) fn parse_args(func_args: Vec) -> Result { +pub(crate) fn parse_arguments( + function_arguments: Vec, +) -> Result { let mut args = vec![]; let mut keywords = vec![]; - let mut keyword_names = - FxHashSet::with_capacity_and_hasher(func_args.len(), BuildHasherDefault::default()); + let mut keyword_names = FxHashSet::with_capacity_and_hasher( + function_arguments.len(), + BuildHasherDefault::default(), + ); let mut double_starred = false; - for (name, value) in func_args { + for (name, value) in function_arguments { if let Some((start, end, name)) = name { // Check for duplicate keyword arguments in the call. if let Some(keyword_name) = &name { @@ -133,15 +140,15 @@ const fn is_starred(exp: &ast::Expr) -> bool { #[cfg(test)] mod tests { use super::*; - use crate::{Parse, ParseErrorType}; - use ruff_python_ast::{self as ast}; + use crate::parser::parse_suite; + use crate::ParseErrorType; macro_rules! function_and_lambda { ($($name:ident: $code:expr,)*) => { $( #[test] fn $name() { - let parse_ast = ast::Suite::parse($code, ""); + let parse_ast = crate::parser::parse_suite($code, ""); insta::assert_debug_snapshot!(parse_ast); } )* @@ -172,7 +179,7 @@ mod tests { } fn function_parse_error(src: &str) -> LexicalErrorType { - let parse_ast = ast::Suite::parse(src, ""); + let parse_ast = parse_suite(src, ""); parse_ast .map_err(|e| match e.error { ParseErrorType::Lexical(e) => e, diff --git a/crates/ruff_python_parser/src/lexer.rs b/crates/ruff_python_parser/src/lexer.rs index a65737c04fe0f..24a4acb3ecb58 100644 --- a/crates/ruff_python_parser/src/lexer.rs +++ b/crates/ruff_python_parser/src/lexer.rs @@ -34,7 +34,7 @@ use std::{char, cmp::Ordering, str::FromStr}; use num_bigint::BigInt; use num_traits::{Num, Zero}; -use ruff_python_ast::MagicKind; +use ruff_python_ast::IpyEscapeKind; use ruff_text_size::{TextLen, TextRange, TextSize}; use unic_emoji_char::is_emoji_presentation; use unic_ucd_ident::{is_xid_continue, is_xid_start}; @@ -398,8 +398,8 @@ impl<'source> Lexer<'source> { Tok::Comment(self.token_text().to_string()) } - /// Lex a single magic command. - fn lex_magic_command(&mut self, kind: MagicKind) -> Tok { + /// Lex a single IPython escape command. + fn lex_ipython_escape_command(&mut self, escape_kind: IpyEscapeKind) -> Tok { let mut value = String::new(); loop { @@ -428,8 +428,77 @@ impl<'source> Lexer<'source> { self.cursor.bump(); value.push('\\'); } + // Help end escape commands are those that end with 1 or 2 question marks. + // Here, we're only looking for a subset of help end escape commands which + // are the ones that has the escape token at the start of the line as well. + // On the other hand, we're not looking for help end escape commands that + // are strict in the sense that the escape token is only at the end. For example, + // + // * `%foo?` is recognized as a help end escape command but not as a strict one. + // * `foo?` is recognized as a strict help end escape command which is not + // lexed here but is identified at the parser level. + // + // Help end escape commands implemented in the IPython codebase using regex: + // https://github.com/ipython/ipython/blob/292e3a23459ca965b8c1bfe2c3707044c510209a/IPython/core/inputtransformer2.py#L454-L462 + '?' => { + self.cursor.bump(); + let mut question_count = 1u32; + while self.cursor.eat_char('?') { + question_count += 1; + } + + // The original implementation in the IPython codebase is based on regex which + // means that it's strict in the sense that it won't recognize a help end escape: + // * If there's any whitespace before the escape token (e.g. `%foo ?`) + // * If there are more than 2 question mark tokens (e.g. `%foo???`) + // which is what we're doing here as well. In that case, we'll continue with + // the prefixed escape token. + // + // Now, the whitespace and empty value check also makes sure that an empty + // command (e.g. `%?` or `? ??`, no value after/between the escape tokens) + // is not recognized as a help end escape command. So, `%?` and `? ??` are + // `IpyEscapeKind::Magic` and `IpyEscapeKind::Help` because of the initial `%` and `??` + // tokens. + if question_count > 2 + || value.chars().last().map_or(true, is_python_whitespace) + || !matches!(self.cursor.first(), '\n' | '\r' | EOF_CHAR) + { + // Not a help end escape command, so continue with the lexing. + value.reserve(question_count as usize); + for _ in 0..question_count { + value.push('?'); + } + continue; + } + + if escape_kind.is_help() { + // If we've recognize this as a help end escape command, then + // any question mark token / whitespaces at the start are not + // considered as part of the value. + // + // For example, `??foo?` is recognized as `IpyEscapeKind::Help` and + // `value` is `foo` instead of `??foo`. + value = value.trim_start_matches([' ', '?']).to_string(); + } else if escape_kind.is_magic() { + // Between `%` and `?` (at the end), the `?` takes priority + // over the `%` so `%foo?` is recognized as `IpyEscapeKind::Help` + // and `value` is `%foo` instead of `foo`. So, we need to + // insert the magic escape token at the start. + value.insert_str(0, escape_kind.as_str()); + } + + let kind = match question_count { + 1 => IpyEscapeKind::Help, + 2 => IpyEscapeKind::Help2, + _ => unreachable!("`question_count` is always 1 or 2"), + }; + return Tok::IpyEscapeCommand { kind, value }; + } '\n' | '\r' | EOF_CHAR => { - return Tok::MagicCommand { kind, value }; + return Tok::IpyEscapeCommand { + kind: escape_kind, + value, + }; } c => { self.cursor.bump(); @@ -697,23 +766,26 @@ impl<'source> Lexer<'source> { && self.state.is_after_equal() && self.nesting == 0 => { - // SAFETY: Safe because `c` has been matched against one of the possible magic command prefix - self.lex_magic_command(MagicKind::try_from(c).unwrap()) + // SAFETY: Safe because `c` has been matched against one of the possible escape command token + self.lex_ipython_escape_command(IpyEscapeKind::try_from(c).unwrap()) } c @ ('%' | '!' | '?' | '/' | ';' | ',') if self.mode == Mode::Jupyter && self.state.is_new_logical_line() => { - let kind = if let Ok(kind) = MagicKind::try_from([c, self.cursor.first()]) { + let kind = if let Ok(kind) = IpyEscapeKind::try_from([c, self.cursor.first()]) { self.cursor.bump(); kind } else { - // SAFETY: Safe because `c` has been matched against one of the possible magic command prefix - MagicKind::try_from(c).unwrap() + // SAFETY: Safe because `c` has been matched against one of the possible escape command token + IpyEscapeKind::try_from(c).unwrap() }; - self.lex_magic_command(kind) + self.lex_ipython_escape_command(kind) } + + '?' if self.mode == Mode::Jupyter => Tok::Question, + '/' => { if self.cursor.eat_char('=') { Tok::SlashEqual @@ -1122,10 +1194,27 @@ fn is_identifier_continuation(c: char) -> bool { } } +/// Returns `true` for [whitespace](https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens) +/// characters. +/// +/// This is the same as `ruff_python_trivia::is_python_whitespace` and is copied +/// here to avoid a circular dependency as `ruff_python_trivia` has a dev-dependency +/// on `ruff_python_lexer`. +const fn is_python_whitespace(c: char) -> bool { + matches!( + c, + // Space, tab, or form-feed + ' ' | '\t' | '\x0C' + ) +} + #[cfg(test)] mod tests { use num_bigint::BigInt; - use ruff_python_ast::MagicKind; + use ruff_python_ast::IpyEscapeKind; + + use insta::assert_debug_snapshot; + use test_case::test_case; use super::*; @@ -1143,61 +1232,36 @@ mod tests { lexer.map(|x| x.unwrap().0).collect() } - fn str_tok(s: &str) -> Tok { - Tok::String { - value: s.to_owned(), - kind: StringKind::String, - triple_quoted: false, - } - } - - fn raw_str_tok(s: &str) -> Tok { - Tok::String { - value: s.to_owned(), - kind: StringKind::RawString, - triple_quoted: false, - } - } - - fn assert_jupyter_magic_line_continuation_with_eol(eol: &str) { + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_ipython_escape_command_line_continuation_eol(eol: &str) { let source = format!("%matplotlib \\{eol} --inline"); let tokens = lex_jupyter_source(&source); assert_eq!( tokens, vec![ - Tok::MagicCommand { + Tok::IpyEscapeCommand { value: "matplotlib --inline".to_string(), - kind: MagicKind::Magic + kind: IpyEscapeKind::Magic }, Tok::Newline ] ); } - #[test] - fn test_jupyter_magic_line_continuation_unix_eol() { - assert_jupyter_magic_line_continuation_with_eol(UNIX_EOL); - } - - #[test] - fn test_jupyter_magic_line_continuation_mac_eol() { - assert_jupyter_magic_line_continuation_with_eol(MAC_EOL); - } - - #[test] - fn test_jupyter_magic_line_continuation_windows_eol() { - assert_jupyter_magic_line_continuation_with_eol(WINDOWS_EOL); - } - - fn assert_jupyter_magic_line_continuation_with_eol_and_eof(eol: &str) { + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_ipython_escape_command_line_continuation_with_eol_and_eof(eol: &str) { let source = format!("%matplotlib \\{eol}"); let tokens = lex_jupyter_source(&source); assert_eq!( tokens, vec![ - Tok::MagicCommand { + Tok::IpyEscapeCommand { value: "matplotlib ".to_string(), - kind: MagicKind::Magic + kind: IpyEscapeKind::Magic }, Tok::Newline ] @@ -1205,78 +1269,13 @@ mod tests { } #[test] - fn test_jupyter_magic_line_continuation_unix_eol_and_eof() { - assert_jupyter_magic_line_continuation_with_eol_and_eof(UNIX_EOL); - } - - #[test] - fn test_jupyter_magic_line_continuation_mac_eol_and_eof() { - assert_jupyter_magic_line_continuation_with_eol_and_eof(MAC_EOL); - } - - #[test] - fn test_jupyter_magic_line_continuation_windows_eol_and_eof() { - assert_jupyter_magic_line_continuation_with_eol_and_eof(WINDOWS_EOL); - } - - #[test] - fn test_empty_jupyter_magic() { + fn test_empty_ipython_escape_command() { let source = "%\n%%\n!\n!!\n?\n??\n/\n,\n;"; - let tokens = lex_jupyter_source(source); - assert_eq!( - tokens, - vec![ - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Magic2, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Shell, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::ShCap, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Help, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Help2, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Paren, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Quote, - }, - Tok::Newline, - Tok::MagicCommand { - value: String::new(), - kind: MagicKind::Quote2, - }, - Tok::Newline, - ] - ); + assert_debug_snapshot!(lex_jupyter_source(source)); } #[test] - fn test_jupyter_magic() { + fn test_ipython_escape_command() { let source = r" ?foo ??foo @@ -1293,96 +1292,46 @@ mod tests { !ls " .trim(); - let tokens = lex_jupyter_source(source); - assert_eq!( - tokens, - vec![ - Tok::MagicCommand { - value: "foo".to_string(), - kind: MagicKind::Help, - }, - Tok::Newline, - Tok::MagicCommand { - value: "foo".to_string(), - kind: MagicKind::Help2, - }, - Tok::Newline, - Tok::MagicCommand { - value: "timeit a = b".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::MagicCommand { - value: "timeit a % 3".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::MagicCommand { - value: "matplotlib --inline".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::MagicCommand { - value: "pwd && ls -a | sed 's/^/\\\\ /'".to_string(), - kind: MagicKind::Shell, - }, - Tok::Newline, - Tok::MagicCommand { - value: "cd /Users/foo/Library/Application\\ Support/".to_string(), - kind: MagicKind::ShCap, - }, - Tok::Newline, - Tok::MagicCommand { - value: "foo 1 2".to_string(), - kind: MagicKind::Paren, - }, - Tok::Newline, - Tok::MagicCommand { - value: "foo 1 2".to_string(), - kind: MagicKind::Quote, - }, - Tok::Newline, - Tok::MagicCommand { - value: "foo 1 2".to_string(), - kind: MagicKind::Quote2, - }, - Tok::Newline, - Tok::MagicCommand { - value: "ls".to_string(), - kind: MagicKind::Shell, - }, - Tok::Newline, - ] - ); + assert_debug_snapshot!(lex_jupyter_source(source)); } + + #[test] + fn test_ipython_help_end_escape_command() { + let source = r" +?foo? +?? foo? +?? foo ? +?foo?? +??foo?? +???foo? +???foo?? +??foo??? +???foo??? +?? \ + foo? +?? \ +? +???? +%foo? +%foo?? +%%foo??? +!pwd?" + .trim(); + assert_debug_snapshot!(lex_jupyter_source(source)); + } + #[test] - fn test_jupyter_magic_indentation() { + fn test_ipython_escape_command_indentation() { let source = r" if True: %matplotlib \ --inline" .trim(); - let tokens = lex_jupyter_source(source); - assert_eq!( - tokens, - vec![ - Tok::If, - Tok::True, - Tok::Colon, - Tok::Newline, - Tok::Indent, - Tok::MagicCommand { - value: "matplotlib --inline".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::Dedent, - ] - ); + assert_debug_snapshot!(lex_jupyter_source(source)); } #[test] - fn test_jupyter_magic_assignment() { + fn test_ipython_escape_command_assignment() { let source = r" pwd = !pwd foo = %timeit a = b @@ -1390,62 +1339,21 @@ bar = %timeit a % 3 baz = %matplotlib \ inline" .trim(); - let tokens = lex_jupyter_source(source); - assert_eq!( - tokens, - vec![ - Tok::Name { - name: "pwd".to_string() - }, - Tok::Equal, - Tok::MagicCommand { - value: "pwd".to_string(), - kind: MagicKind::Shell, - }, - Tok::Newline, - Tok::Name { - name: "foo".to_string() - }, - Tok::Equal, - Tok::MagicCommand { - value: "timeit a = b".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::Name { - name: "bar".to_string() - }, - Tok::Equal, - Tok::MagicCommand { - value: "timeit a % 3".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - Tok::Name { - name: "baz".to_string() - }, - Tok::Equal, - Tok::MagicCommand { - value: "matplotlib inline".to_string(), - kind: MagicKind::Magic, - }, - Tok::Newline, - ] - ); + assert_debug_snapshot!(lex_jupyter_source(source)); } - fn assert_no_jupyter_magic(tokens: &[Tok]) { + fn assert_no_ipython_escape_command(tokens: &[Tok]) { for tok in tokens { - if let Tok::MagicCommand { .. } = tok { - panic!("Unexpected magic command token: {tok:?}") + if let Tok::IpyEscapeCommand { .. } = tok { + panic!("Unexpected escape command token: {tok:?}") } } } #[test] - fn test_jupyter_magic_not_an_assignment() { + fn test_ipython_escape_command_not_an_assignment() { let source = r" -# Other magic kinds are not valid here (can't test `foo = ?str` because '?' is not a valid token) +# Other escape kinds are not valid here (can't test `foo = ?str` because '?' is not a valid token) foo = /func foo = ;func foo = ,func @@ -1456,266 +1364,172 @@ def f(arg=%timeit a = b): pass" .trim(); let tokens = lex_jupyter_source(source); - assert_no_jupyter_magic(&tokens); + assert_no_ipython_escape_command(&tokens); } #[test] fn test_numbers() { let source = "0x2f 0o12 0b1101 0 123 123_45_67_890 0.2 1e+2 2.1e3 2j 2.2j"; - let tokens = lex_source(source); + assert_debug_snapshot!(lex_source(source)); + } + + #[test_case(" foo"; "long")] + #[test_case(" "; "whitespace")] + #[test_case(" "; "single whitespace")] + #[test_case(""; "empty")] + fn test_line_comment(comment: &str) { + let source = format!("99232 # {comment}"); + let tokens = lex_source(&source); assert_eq!( tokens, vec![ Tok::Int { - value: BigInt::from(47), - }, - Tok::Int { - value: BigInt::from(10) - }, - Tok::Int { - value: BigInt::from(13), - }, - Tok::Int { - value: BigInt::from(0), + value: BigInt::from(99232) }, + Tok::Comment(format!("# {comment}")), + Tok::Newline + ] + ); + } + + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_comment_until_eol(eol: &str) { + let source = format!("123 # Foo{eol}456"); + let tokens = lex_source(&source); + assert_eq!( + tokens, + vec![ Tok::Int { - value: BigInt::from(123), + value: BigInt::from(123) }, + Tok::Comment("# Foo".to_string()), + Tok::Newline, Tok::Int { - value: BigInt::from(1_234_567_890), - }, - Tok::Float { value: 0.2 }, - Tok::Float { value: 100.0 }, - Tok::Float { value: 2100.0 }, - Tok::Complex { - real: 0.0, - imag: 2.0, - }, - Tok::Complex { - real: 0.0, - imag: 2.2, + value: BigInt::from(456) }, Tok::Newline, ] ); } - macro_rules! test_line_comment { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = format!(r"99232 # {}", $eol); - let tokens = lex_source(&source); - assert_eq!(tokens, vec![Tok::Int { value: BigInt::from(99232) }, Tok::Comment(format!("# {}", $eol)), Tok::Newline]); - } - )* - } - } - - test_line_comment! { - test_line_comment_long: " foo", - test_line_comment_whitespace: " ", - test_line_comment_single_whitespace: " ", - test_line_comment_empty: "", - } - - macro_rules! test_comment_until_eol { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = format!("123 # Foo{}456", $eol); - let tokens = lex_source(&source); - assert_eq!( - tokens, - vec![ - Tok::Int { value: BigInt::from(123) }, - Tok::Comment("# Foo".to_string()), - Tok::Newline, - Tok::Int { value: BigInt::from(456) }, - Tok::Newline, - ] - ) - } - )* - } - } - - test_comment_until_eol! { - test_comment_until_windows_eol: WINDOWS_EOL, - test_comment_until_mac_eol: MAC_EOL, - test_comment_until_unix_eol: UNIX_EOL, - } - #[test] fn test_assignment() { let source = r"a_variable = 99 + 2-0"; - let tokens = lex_source(source); + assert_debug_snapshot!(lex_source(source)); + } + + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_indentation_with_eol(eol: &str) { + let source = format!("def foo():{eol} return 99{eol}{eol}"); + let tokens = lex_source(&source); assert_eq!( tokens, vec![ + Tok::Def, Tok::Name { - name: String::from("a_variable"), + name: String::from("foo"), }, - Tok::Equal, + Tok::Lpar, + Tok::Rpar, + Tok::Colon, + Tok::Newline, + Tok::Indent, + Tok::Return, Tok::Int { value: BigInt::from(99) }, - Tok::Plus, - Tok::Int { - value: BigInt::from(2) + Tok::Newline, + Tok::NonLogicalNewline, + Tok::Dedent, + ] + ); + } + + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_double_dedent_with_eol(eol: &str) { + let source = format!("def foo():{eol} if x:{eol}{eol} return 99{eol}{eol}"); + let tokens = lex_source(&source); + assert_eq!( + tokens, + vec![ + Tok::Def, + Tok::Name { + name: String::from("foo"), + }, + Tok::Lpar, + Tok::Rpar, + Tok::Colon, + Tok::Newline, + Tok::Indent, + Tok::If, + Tok::Name { + name: String::from("x"), }, - Tok::Minus, + Tok::Colon, + Tok::Newline, + Tok::NonLogicalNewline, + Tok::Indent, + Tok::Return, Tok::Int { - value: BigInt::from(0) + value: BigInt::from(99) }, Tok::Newline, + Tok::NonLogicalNewline, + Tok::Dedent, + Tok::Dedent, ] ); } - macro_rules! test_indentation_with_eol { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = format!("def foo():{} return 99{}{}", $eol, $eol, $eol); - let tokens = lex_source(&source); - assert_eq!( - tokens, - vec![ - Tok::Def, - Tok::Name { - name: String::from("foo"), - }, - Tok::Lpar, - Tok::Rpar, - Tok::Colon, - Tok::Newline, - Tok::Indent, - Tok::Return, - Tok::Int { value: BigInt::from(99) }, - Tok::Newline, - Tok::NonLogicalNewline, - Tok::Dedent, - ] - ); - } - )* - }; - } - - test_indentation_with_eol! { - test_indentation_windows_eol: WINDOWS_EOL, - test_indentation_mac_eol: MAC_EOL, - test_indentation_unix_eol: UNIX_EOL, - } - - macro_rules! test_double_dedent_with_eol { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = format!("def foo():{} if x:{}{} return 99{}{}", $eol, $eol, $eol, $eol, $eol); - let tokens = lex_source(&source); - assert_eq!( - tokens, - vec![ - Tok::Def, - Tok::Name { - name: String::from("foo"), - }, - Tok::Lpar, - Tok::Rpar, - Tok::Colon, - Tok::Newline, - Tok::Indent, - Tok::If, - Tok::Name { - name: String::from("x"), - }, - Tok::Colon, - Tok::Newline, - Tok::NonLogicalNewline, - Tok::Indent, - Tok::Return, - Tok::Int { value: BigInt::from(99) }, - Tok::Newline, - Tok::NonLogicalNewline, - Tok::Dedent, - Tok::Dedent, - ] - ); - } - )* - } - } - - macro_rules! test_double_dedent_with_tabs { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = format!("def foo():{}\tif x:{}{}\t return 99{}{}", $eol, $eol, $eol, $eol, $eol); - let tokens = lex_source(&source); - assert_eq!( - tokens, - vec![ - Tok::Def, - Tok::Name { - name: String::from("foo"), - }, - Tok::Lpar, - Tok::Rpar, - Tok::Colon, - Tok::Newline, - Tok::Indent, - Tok::If, - Tok::Name { - name: String::from("x"), - }, - Tok::Colon, - Tok::Newline, - Tok::NonLogicalNewline, - Tok::Indent, - Tok::Return, - Tok::Int { value: BigInt::from(99) }, - Tok::Newline, - Tok::NonLogicalNewline, - Tok::Dedent, - Tok::Dedent, - ] - ); - } - )* - } - } - - test_double_dedent_with_eol! { - test_double_dedent_windows_eol: WINDOWS_EOL, - test_double_dedent_mac_eol: MAC_EOL, - test_double_dedent_unix_eol: UNIX_EOL, - } - - test_double_dedent_with_tabs! { - test_double_dedent_tabs_windows_eol: WINDOWS_EOL, - test_double_dedent_tabs_mac_eol: MAC_EOL, - test_double_dedent_tabs_unix_eol: UNIX_EOL, + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_double_dedent_with_tabs(eol: &str) { + let source = format!("def foo():{eol}\tif x:{eol}{eol}\t\t return 99{eol}{eol}"); + let tokens = lex_source(&source); + assert_eq!( + tokens, + vec![ + Tok::Def, + Tok::Name { + name: String::from("foo"), + }, + Tok::Lpar, + Tok::Rpar, + Tok::Colon, + Tok::Newline, + Tok::Indent, + Tok::If, + Tok::Name { + name: String::from("x"), + }, + Tok::Colon, + Tok::Newline, + Tok::NonLogicalNewline, + Tok::Indent, + Tok::Return, + Tok::Int { + value: BigInt::from(99) + }, + Tok::Newline, + Tok::NonLogicalNewline, + Tok::Dedent, + Tok::Dedent, + ] + ); } - macro_rules! test_newline_in_brackets { - ($($name:ident: $eol:expr,)*) => { - $( - #[test] - - fn $name() { - let source = r"x = [ + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_newline_in_brackets(eol: &str) { + let source = r"x = [ 1,2 ,(3, @@ -1724,172 +1538,134 @@ def f(arg=%timeit a = b): 5, 6,\ 7}] -".replace("\n", $eol); - let tokens = lex_source(&source); - assert_eq!( - tokens, - vec![ - Tok::Name { - name: String::from("x"), - }, - Tok::Equal, - Tok::Lsqb, - Tok::NonLogicalNewline, - Tok::NonLogicalNewline, - Tok::Int { value: BigInt::from(1) }, - Tok::Comma, - Tok::Int { value: BigInt::from(2) }, - Tok::NonLogicalNewline, - Tok::Comma, - Tok::Lpar, - Tok::Int { value: BigInt::from(3) }, - Tok::Comma, - Tok::NonLogicalNewline, - Tok::Int { value: BigInt::from(4) }, - Tok::Comma, - Tok::NonLogicalNewline, - Tok::Rpar, - Tok::Comma, - Tok::Lbrace, - Tok::NonLogicalNewline, - Tok::Int { value: BigInt::from(5) }, - Tok::Comma, - Tok::NonLogicalNewline, - Tok::Int { value: BigInt::from(6) }, - Tok::Comma, - // Continuation here - no NonLogicalNewline. - Tok::Int { value: BigInt::from(7) }, - Tok::Rbrace, - Tok::Rsqb, - Tok::Newline, - ] - ); - } - )* - }; - } - - test_newline_in_brackets! { - test_newline_in_brackets_windows_eol: WINDOWS_EOL, - test_newline_in_brackets_mac_eol: MAC_EOL, - test_newline_in_brackets_unix_eol: UNIX_EOL, - } - - #[test] - fn test_non_logical_newline_in_string_continuation() { - let source = r"( - 'a' - 'b' - - 'c' \ - 'd' -)"; - let tokens = lex_source(source); +" + .replace('\n', eol); + let tokens = lex_source(&source); assert_eq!( tokens, vec![ - Tok::Lpar, + Tok::Name { + name: String::from("x"), + }, + Tok::Equal, + Tok::Lsqb, Tok::NonLogicalNewline, - str_tok("a"), Tok::NonLogicalNewline, - str_tok("b"), + Tok::Int { + value: BigInt::from(1) + }, + Tok::Comma, + Tok::Int { + value: BigInt::from(2) + }, Tok::NonLogicalNewline, + Tok::Comma, + Tok::Lpar, + Tok::Int { + value: BigInt::from(3) + }, + Tok::Comma, Tok::NonLogicalNewline, - str_tok("c"), - str_tok("d"), + Tok::Int { + value: BigInt::from(4) + }, + Tok::Comma, Tok::NonLogicalNewline, Tok::Rpar, + Tok::Comma, + Tok::Lbrace, + Tok::NonLogicalNewline, + Tok::Int { + value: BigInt::from(5) + }, + Tok::Comma, + Tok::NonLogicalNewline, + Tok::Int { + value: BigInt::from(6) + }, + Tok::Comma, + // Continuation here - no NonLogicalNewline. + Tok::Int { + value: BigInt::from(7) + }, + Tok::Rbrace, + Tok::Rsqb, Tok::Newline, ] ); } + #[test] + fn test_non_logical_newline_in_string_continuation() { + let source = r"( + 'a' + 'b' + + 'c' \ + 'd' +)"; + assert_debug_snapshot!(lex_source(source)); + } + #[test] fn test_logical_newline_line_comment() { let source = "#Hello\n#World\n"; - let tokens = lex_source(source); - assert_eq!( - tokens, - vec![ - Tok::Comment("#Hello".to_owned()), - Tok::NonLogicalNewline, - Tok::Comment("#World".to_owned()), - Tok::NonLogicalNewline, - ] - ); + assert_debug_snapshot!(lex_source(source)); } #[test] fn test_operators() { let source = "//////=/ /"; - let tokens = lex_source(source); - assert_eq!( - tokens, - vec![ - Tok::DoubleSlash, - Tok::DoubleSlash, - Tok::DoubleSlashEqual, - Tok::Slash, - Tok::Slash, - Tok::Newline, - ] - ); + assert_debug_snapshot!(lex_source(source)); } #[test] fn test_string() { let source = r#""double" 'single' 'can\'t' "\\\"" '\t\r\n' '\g' r'raw\'' '\420' '\200\0a'"#; - let tokens = lex_source(source); - assert_eq!( - tokens, - vec![ - str_tok("double"), - str_tok("single"), - str_tok(r"can\'t"), - str_tok(r#"\\\""#), - str_tok(r"\t\r\n"), - str_tok(r"\g"), - raw_str_tok(r"raw\'"), - str_tok(r"\420"), - str_tok(r"\200\0a"), - Tok::Newline, - ] - ); + assert_debug_snapshot!(lex_source(source)); } - fn assert_string_continuation_with_eol(eol: &str) { + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_string_continuation_with_eol(eol: &str) { let source = format!("\"abc\\{eol}def\""); let tokens = lex_source(&source); assert_eq!( tokens, - vec![str_tok(&format!("abc\\{eol}def")), Tok::Newline] + vec![ + Tok::String { + value: format!("abc\\{eol}def"), + kind: StringKind::String, + triple_quoted: false, + }, + Tok::Newline, + ] ); } - #[test] - fn test_string_continuation_windows_eol() { - assert_string_continuation_with_eol(WINDOWS_EOL); - } - - #[test] - fn test_string_continuation_mac_eol() { - assert_string_continuation_with_eol(MAC_EOL); - } - - #[test] - fn test_string_continuation_unix_eol() { - assert_string_continuation_with_eol(UNIX_EOL); - } - #[test] fn test_escape_unicode_name() { let source = r#""\N{EN SPACE}""#; let tokens = lex_source(source); - assert_eq!(tokens, vec![str_tok(r"\N{EN SPACE}"), Tok::Newline]); + assert_eq!( + tokens, + vec![ + Tok::String { + value: r"\N{EN SPACE}".to_string(), + kind: StringKind::String, + triple_quoted: false, + }, + Tok::Newline + ] + ); } - fn assert_triple_quoted(eol: &str) { + #[test_case(UNIX_EOL)] + #[test_case(MAC_EOL)] + #[test_case(WINDOWS_EOL)] + fn test_triple_quoted(eol: &str) { let source = format!("\"\"\"{eol} test string{eol} \"\"\""); let tokens = lex_source(&source); assert_eq!( @@ -1904,19 +1680,4 @@ def f(arg=%timeit a = b): ] ); } - - #[test] - fn triple_quoted_windows_eol() { - assert_triple_quoted(WINDOWS_EOL); - } - - #[test] - fn triple_quoted_unix_eol() { - assert_triple_quoted(UNIX_EOL); - } - - #[test] - fn triple_quoted_macos_eol() { - assert_triple_quoted(MAC_EOL); - } } diff --git a/crates/ruff_python_parser/src/lib.rs b/crates/ruff_python_parser/src/lib.rs index ac00c8ddcbdfe..8cb1774d29bb1 100644 --- a/crates/ruff_python_parser/src/lib.rs +++ b/crates/ruff_python_parser/src/lib.rs @@ -94,14 +94,13 @@ //! mode or tokenizing the source beforehand: //! //! ``` -//! use ruff_python_parser::{Parse}; -//! use ruff_python_ast as ast; +//! use ruff_python_parser::parse_suite; //! //! let python_source = r#" //! def is_odd(i): //! return bool(i & 1) //! "#; -//! let ast = ast::Suite::parse(python_source, ""); +//! let ast = parse_suite(python_source, ""); //! //! assert!(ast.is_ok()); //! ``` @@ -110,21 +109,21 @@ //! [parsing]: https://en.wikipedia.org/wiki/Parsing //! [lexer]: crate::lexer -use crate::lexer::LexResult; -pub use parse::Parse; -pub use parser::{parse, parse_starts_at, parse_tokens, ParseError, ParseErrorType}; -#[allow(deprecated)] -pub use parser::{parse_expression, parse_expression_starts_at, parse_program}; -use ruff_python_ast::{CmpOp, Expr, ModModule, Ranged, Suite}; +pub use parser::{ + parse, parse_expression, parse_expression_starts_at, parse_program, parse_starts_at, + parse_suite, parse_tokens, ParseError, ParseErrorType, +}; +use ruff_python_ast::{CmpOp, Expr, Mod, PySourceType, Ranged, Suite}; use ruff_text_size::{TextRange, TextSize}; pub use string::FStringErrorType; pub use token::{StringKind, Tok, TokenKind}; +use crate::lexer::LexResult; + mod function; // Skip flattening lexer to distinguish from full ruff_python_parser mod context; pub mod lexer; -mod parse; mod parser; mod soft_keywords; mod string; @@ -132,9 +131,9 @@ mod token; pub mod typing; /// Collect tokens up to and including the first error. -pub fn tokenize(contents: &str) -> Vec { +pub fn tokenize(contents: &str, mode: Mode) -> Vec { let mut tokens: Vec = vec![]; - for tok in lexer::lex(contents, Mode::Module) { + for tok in lexer::lex(contents, mode) { let is_err = tok.is_err(); tokens.push(tok); if is_err { @@ -148,18 +147,17 @@ pub fn tokenize(contents: &str) -> Vec { pub fn parse_program_tokens( lxr: Vec, source_path: &str, + is_jupyter_notebook: bool, ) -> anyhow::Result { - ModModule::parse_tokens(lxr, source_path).map(|module| module.body) -} - -/// Return the `Range` of the first `Tok::Colon` token in a `Range`. -pub fn first_colon_range(range: TextRange, source: &str) -> Option { - let contents = &source[range]; - let range = lexer::lex_starts_at(contents, Mode::Module, range.start()) - .flatten() - .find(|(tok, _)| tok.is_colon()) - .map(|(_, range)| range); - range + let mode = if is_jupyter_notebook { + Mode::Jupyter + } else { + Mode::Module + }; + match parse_tokens(lxr, mode, source_path)? { + Mod::Module(m) => Ok(m.body), + Mod::Expression(_) => unreachable!("Mode::Module doesn't return other variant"), + } } /// Extract all [`CmpOp`] operators from an expression snippet, with appropriate @@ -307,6 +305,19 @@ impl std::str::FromStr for Mode { } } +pub trait AsMode { + fn as_mode(&self) -> Mode; +} + +impl AsMode for PySourceType { + fn as_mode(&self) -> Mode { + match self { + PySourceType::Python | PySourceType::Stub => Mode::Module, + PySourceType::Ipynb => Mode::Jupyter, + } + } +} + /// Returned when a given mode is not valid. #[derive(Debug)] pub struct ModeParseError; @@ -344,29 +355,17 @@ mod python { #[cfg(test)] mod tests { - use crate::Parse; - use crate::{first_colon_range, locate_cmp_ops, LocatedCmpOp}; use anyhow::Result; + use ruff_python_ast::CmpOp; - use ruff_python_ast::Expr; - use ruff_text_size::{TextLen, TextRange, TextSize}; + use ruff_text_size::TextSize; - #[test] - fn extract_first_colon_range() { - let contents = "with a: pass"; - let range = first_colon_range( - TextRange::new(TextSize::from(0), contents.text_len()), - contents, - ) - .unwrap(); - assert_eq!(&contents[range], ":"); - assert_eq!(range, TextRange::new(TextSize::from(6), TextSize::from(7))); - } + use crate::{locate_cmp_ops, parse_expression, LocatedCmpOp}; #[test] fn extract_cmp_op_location() -> Result<()> { let contents = "x == 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -376,7 +375,7 @@ mod tests { ); let contents = "x != 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -386,7 +385,7 @@ mod tests { ); let contents = "x is 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -396,7 +395,7 @@ mod tests { ); let contents = "x is not 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -406,7 +405,7 @@ mod tests { ); let contents = "x in 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -416,7 +415,7 @@ mod tests { ); let contents = "x not in 1"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( @@ -426,7 +425,7 @@ mod tests { ); let contents = "x != (1 is not 2)"; - let expr = Expr::parse(contents, "")?; + let expr = parse_expression(contents, "")?; assert_eq!( locate_cmp_ops(&expr, contents), vec![LocatedCmpOp::new( diff --git a/crates/ruff_python_parser/src/parse.rs b/crates/ruff_python_parser/src/parse.rs deleted file mode 100644 index ab6ab7d5a1e4e..0000000000000 --- a/crates/ruff_python_parser/src/parse.rs +++ /dev/null @@ -1,1177 +0,0 @@ -use crate::lexer::{lex, lex_starts_at, LexResult}; -use crate::{parse_tokens, Mode, ParseError, ParseErrorType}; -use ruff_python_ast as ast; -use ruff_python_ast::Ranged; -use ruff_text_size::TextSize; - -/// Parse Python code string to implementor's type. -/// -/// # Example -/// -/// For example, parsing a simple function definition and a call to that function: -/// -/// ``` -/// use ruff_python_parser::{self as parser, Parse}; -/// use ruff_python_ast as ast; -/// let source = r#" -/// def foo(): -/// return 42 -/// -/// print(foo()) -/// "#; -/// let program = ast::Suite::parse(source, ""); -/// assert!(program.is_ok()); -/// ``` -/// -/// Parsing a single expression denoting the addition of two numbers, but this time specifying a different, -/// somewhat silly, location: -/// -/// ``` -/// # use ruff_text_size::TextSize; -/// # use ruff_python_ast as ast; -/// # use ruff_python_parser::{self as parser, Parse}; -/// -/// let expr = ast::Expr::parse_starts_at("1 + 2", "", TextSize::from(400)); -/// assert!(expr.is_ok()); -pub trait Parse -where - Self: Sized, -{ - const MODE: Mode; - - fn parse(source: &str, source_path: &str) -> Result { - let tokens = lex(source, Self::MODE); - - Self::parse_tokens(tokens, source_path) - } - - fn parse_without_path(source: &str) -> Result { - Self::parse(source, "") - } - - fn parse_starts_at( - source: &str, - source_path: &str, - offset: TextSize, - ) -> Result { - let tokens = lex_starts_at(source, Self::MODE, offset); - - Self::parse_tokens(tokens, source_path) - } - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result; -} - -impl Parse for ast::ModModule { - const MODE: Mode = Mode::Module; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - match parse_tokens(lxr, Mode::Module, source_path)? { - ast::Mod::Module(m) => Ok(m), - ast::Mod::Expression(_) => unreachable!("Mode::Module doesn't return other variant"), - } - } -} - -impl Parse for ast::ModExpression { - const MODE: Mode = Mode::Expression; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - match parse_tokens(lxr, Mode::Expression, source_path)? { - ast::Mod::Expression(m) => Ok(m), - ast::Mod::Module(_) => unreachable!("Mode::Module doesn't return other variant"), - } - } -} - -impl Parse for ast::Suite { - const MODE: Mode = Mode::Module; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - Ok(ast::ModModule::parse_tokens(lxr, source_path)?.body) - } -} - -impl Parse for ast::Stmt { - const MODE: Mode = Mode::Module; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let mut statements = ast::ModModule::parse_tokens(lxr, source_path)?.body; - let statement = match statements.len() { - 0 => { - return Err(ParseError { - error: ParseErrorType::Eof, - offset: TextSize::default(), - source_path: source_path.to_owned(), - }) - } - 1 => statements.pop().unwrap(), - _ => { - return Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: statements[1].range().start(), - source_path: source_path.to_owned(), - }) - } - }; - Ok(statement) - } -} - -impl Parse for ast::Expr { - const MODE: Mode = Mode::Expression; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - Ok(*ast::ModExpression::parse_tokens(lxr, source_path)?.body) - } -} - -impl Parse for ast::Identifier { - const MODE: Mode = Mode::Expression; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let expr = ast::Expr::parse_tokens(lxr, source_path)?; - match expr { - ast::Expr::Name(name) => { - let range = name.range(); - Ok(ast::Identifier::new(name.id, range)) - } - expr => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: expr.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::Constant { - const MODE: Mode = Mode::Expression; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let expr = ast::Expr::parse_tokens(lxr, source_path)?; - match expr { - ast::Expr::Constant(c) => Ok(c.value), - expr => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: expr.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtFunctionDef { - const MODE: Mode = Mode::Module; - - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::FunctionDef(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAsyncFunctionDef { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::AsyncFunctionDef(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtClassDef { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::ClassDef(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtReturn { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Return(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtDelete { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Delete(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAssign { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Assign(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtTypeAlias { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::TypeAlias(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAugAssign { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::AugAssign(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAnnAssign { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::AnnAssign(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtFor { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::For(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAsyncFor { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::AsyncFor(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtWhile { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::While(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtIf { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::If(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtWith { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::With(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAsyncWith { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::AsyncWith(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtMatch { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Match(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtRaise { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Raise(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtTry { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Try(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtTryStar { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::TryStar(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtAssert { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Assert(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtImport { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Import(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtImportFrom { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::ImportFrom(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtGlobal { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Global(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtNonlocal { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Nonlocal(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtExpr { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Expr(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtPass { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Pass(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtBreak { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Break(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::StmtContinue { - const MODE: Mode = Mode::Module; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Stmt::parse_tokens(lxr, source_path)?; - match node { - ast::Stmt::Continue(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprBoolOp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::BoolOp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprNamedExpr { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::NamedExpr(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprBinOp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::BinOp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprUnaryOp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::UnaryOp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprLambda { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Lambda(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprIfExp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::IfExp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprDict { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Dict(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprSet { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Set(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprListComp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::ListComp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprSetComp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::SetComp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprDictComp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::DictComp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprGeneratorExp { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::GeneratorExp(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprAwait { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Await(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprYield { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Yield(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprYieldFrom { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::YieldFrom(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprCompare { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Compare(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprCall { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Call(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprFormattedValue { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::FormattedValue(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprJoinedStr { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::JoinedStr(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprConstant { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Constant(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprAttribute { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Attribute(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprSubscript { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Subscript(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprStarred { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Starred(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprName { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Name(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprList { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::List(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprTuple { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Tuple(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} - -impl Parse for ast::ExprSlice { - const MODE: Mode = Mode::Expression; - fn parse_tokens( - lxr: impl IntoIterator, - source_path: &str, - ) -> Result { - let node = ast::Expr::parse_tokens(lxr, source_path)?; - match node { - ast::Expr::Slice(node) => Ok(node), - node => Err(ParseError { - error: ParseErrorType::InvalidToken, - offset: node.range().start(), - source_path: source_path.to_owned(), - }), - } - } -} diff --git a/crates/ruff_python_parser/src/parser.rs b/crates/ruff_python_parser/src/parser.rs index df09c8e5e3c10..8ffc2078e11a3 100644 --- a/crates/ruff_python_parser/src/parser.rs +++ b/crates/ruff_python_parser/src/parser.rs @@ -18,14 +18,15 @@ use itertools::Itertools; pub(super) use lalrpop_util::ParseError as LalrpopError; use ruff_text_size::{TextRange, TextSize}; +use crate::lexer::{lex, lex_starts_at}; use crate::{ lexer::{self, LexResult, LexicalError, LexicalErrorType}, python, token::Tok, - Mode, Parse, + Mode, }; use ruff_python_ast as ast; -use ruff_python_ast::ModModule; +use ruff_python_ast::{Mod, ModModule, Suite}; /// Parse a full Python program usually consisting of multiple lines. /// @@ -47,9 +48,16 @@ use ruff_python_ast::ModModule; /// let program = parser::parse_program(source, ""); /// assert!(program.is_ok()); /// ``` -#[deprecated = "Use ruff_python_ast::Suite::parse from ruff_python_parser::Parse trait."] -pub fn parse_program(source: &str, source_path: &str) -> Result { - ModModule::parse(source, source_path).map(|module| module.body) +pub fn parse_program(source: &str, source_path: &str) -> Result { + let lexer = lex(source, Mode::Module); + match parse_tokens(lexer, Mode::Module, source_path)? { + Mod::Module(m) => Ok(m), + Mod::Expression(_) => unreachable!("Mode::Module doesn't return other variant"), + } +} + +pub fn parse_suite(source: &str, source_path: &str) -> Result { + parse_program(source, source_path).map(|m| m.body) } /// Parses a single Python expression. @@ -68,9 +76,12 @@ pub fn parse_program(source: &str, source_path: &str) -> Result Result { - ast::Expr::parse(source, path) +pub fn parse_expression(source: &str, source_path: &str) -> Result { + let lexer = lex(source, Mode::Expression); + match parse_tokens(lexer, Mode::Expression, source_path)? { + Mod::Expression(expression) => Ok(*expression.body), + Mod::Module(_m) => unreachable!("Mode::Expression doesn't return other variant"), + } } /// Parses a Python expression from a given location. @@ -90,20 +101,23 @@ pub fn parse_expression(source: &str, path: &str) -> Result", TextSize::from(400)); /// assert!(expr.is_ok()); /// ``` -#[deprecated = "Use ruff_python_ast::Expr::parse_starts_at from ruff_python_parser::Parse trait."] pub fn parse_expression_starts_at( source: &str, - path: &str, + source_path: &str, offset: TextSize, ) -> Result { - ast::Expr::parse_starts_at(source, path, offset) + let lexer = lex_starts_at(source, Mode::Module, offset); + match parse_tokens(lexer, Mode::Expression, source_path)? { + Mod::Expression(expression) => Ok(*expression.body), + Mod::Module(_m) => unreachable!("Mode::Expression doesn't return other variant"), + } } /// Parse the given Python source code using the specified [`Mode`]. /// /// This function is the most general function to parse Python code. Based on the [`Mode`] supplied, /// it can be used to parse a single expression, a full Python program, an interactive expression -/// or a Python program containing Jupyter magics. +/// or a Python program containing IPython escape commands. /// /// # Example /// @@ -132,7 +146,7 @@ pub fn parse_expression_starts_at( /// assert!(program.is_ok()); /// ``` /// -/// Additionally, we can parse a Python program containing Jupyter magics: +/// Additionally, we can parse a Python program containing IPython escapes: /// /// ``` /// use ruff_python_parser::{Mode, parse}; @@ -384,71 +398,69 @@ impl ParseErrorType { #[cfg(test)] mod tests { - use crate::Parse; use insta::assert_debug_snapshot; - use ruff_python_ast as ast; use super::*; #[test] fn test_parse_empty() { - let parse_ast = ast::Suite::parse("", "").unwrap(); + let parse_ast = parse_suite("", "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_string() { let source = "'Hello world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_f_string() { let source = "f'Hello world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_print_hello() { let source = "print('Hello world')"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_print_2() { let source = "print('Hello world', 2)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_kwargs() { let source = "my_func('positional', keyword=2)"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_if_elif_else() { let source = "if 1: 10\nelif 2: 20\nelse: 30"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_lambda() { let source = "lambda x, y: x * y"; // lambda(x, y): x * y"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_lambda_no_args() { let source = "lambda: 1"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -456,7 +468,7 @@ mod tests { fn test_parse_tuples() { let source = "a, b = 4, 5"; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -468,7 +480,7 @@ class Foo(A, B): def method_with_default(self, arg='default'): pass "; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -499,7 +511,7 @@ class Foo[**P](): ... class Foo[X, Y: str, *U, **P](): pass "; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] fn test_parse_function_definition() { @@ -525,69 +537,76 @@ def func[**P](*args: P.args, **kwargs: P.kwargs): def func[T, U: str, *Ts, **P](): pass "; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] fn test_parse_dict_comprehension() { let source = "{x1: x2 for y in z}"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_list_comprehension() { let source = "[x for y in z]"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_double_list_comprehension() { let source = "[x for y, y2 in z for a in b if a < 5 if a > 10]"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_generator_comprehension() { let source = "(x for y in z)"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_named_expression_generator_comprehension() { let source = "(x := y + 1 for y in z)"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_if_else_generator_comprehension() { let source = "(x if y else y for y in z)"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_bool_op_or() { let source = "x or y"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_bool_op_and() { let source = "x and y"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_slice() { let source = "x[1:2:3]"; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } + + #[test] + fn test_named_expression() { + let source = "(x := ( y * z ))"; + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -621,7 +640,7 @@ with (0 as a,): pass with (0 as a, 1 as b): pass with (0 as a, 1 as b,): pass "; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -644,7 +663,7 @@ with (0 as a, 1 as b,): pass "with a := 0 as x: pass", "with (a := 0 as x): pass", ] { - assert!(ast::Suite::parse(source, "").is_err()); + assert!(parse_suite(source, "").is_err()); } } @@ -656,7 +675,7 @@ array[0, *indexes, -1] = array_slice array[*indexes_to_select, *indexes_to_select] array[3:5, *indexes_to_select] "; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -669,13 +688,13 @@ array[3:5, *indexes_to_select] ("OFFSET %d" % offset) if offset else None, ) )"#; - let parse_ast = ast::Expr::parse(source, "").unwrap(); + let parse_ast = parse_expression(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_try() { - let parse_ast = ast::Suite::parse( + let parse_ast = parse_suite( r#"try: raise ValueError(1) except TypeError as e: @@ -690,7 +709,7 @@ except OSError as e: #[test] fn test_try_star() { - let parse_ast = ast::Suite::parse( + let parse_ast = parse_suite( r#"try: raise ExceptionGroup("eg", [ValueError(1), TypeError(2), OSError(3), OSError(4)]) @@ -706,7 +725,7 @@ except* OSError as e: #[test] fn test_dict_unpacking() { - let parse_ast = ast::Expr::parse(r#"{"a": "b", **c, "d": "e"}"#, "").unwrap(); + let parse_ast = parse_expression(r#"{"a": "b", **c, "d": "e"}"#, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -758,12 +777,12 @@ type X \ type X[T] \ = T "#; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] fn test_type_as_identifier() { - let source = r#"\ + let source = r"\ type *a + b, c # ((type * a) + b), c type *(a + b), c # (type * (a + b)), c type (*a + b, c) # type ((*(a + b)), c) @@ -794,8 +813,8 @@ type ( type = 1 type = x = 1 x = type = 1 -"#; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); +"; + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -820,7 +839,7 @@ x = 10000 x = 133333 "#; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -846,12 +865,12 @@ if 10 .real: y = 100[no] y = 100(no) "#; - assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); + assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] fn test_match_as_identifier() { - let source = r#"\ + let source = r"\ match *a + b, c # ((match * a) + b), c match *(a + b), c # (match * (a + b)), c match (*a + b, c) # match ((*(a + b)), c) @@ -873,8 +892,8 @@ match match: pass match = lambda query: query == event print(match(12)) -"#; - insta::assert_debug_snapshot!(ast::Suite::parse(source, "").unwrap()); +"; + insta::assert_debug_snapshot!(parse_suite(source, "").unwrap()); } #[test] @@ -1044,13 +1063,13 @@ match w := x,: case y as v,: z = 0 "#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_match() { - let parse_ast = ast::Suite::parse( + let parse_ast = parse_suite( r#" match {"test": 1}: case { @@ -1080,7 +1099,7 @@ match x: #[test] fn test_variadic_generics() { - let parse_ast = ast::Suite::parse( + let parse_ast = parse_suite( r#" def args_to_tuple(*args: *Ts) -> Tuple[*Ts]: ... "#, @@ -1090,26 +1109,9 @@ def args_to_tuple(*args: *Ts) -> Tuple[*Ts]: ... insta::assert_debug_snapshot!(parse_ast); } - #[test] - fn test_parse_constant() { - use num_traits::ToPrimitive; - - let c = ast::Constant::parse_without_path("'string'").unwrap(); - assert_eq!(c.str().unwrap(), "string"); - - let c = ast::Constant::parse_without_path("10").unwrap(); - assert_eq!(c.int().unwrap().to_i32().unwrap(), 10); - } - - #[test] - fn test_parse_identifier() { - let i = ast::Identifier::parse_without_path("test").unwrap(); - assert_eq!(i.as_str(), "test"); - } - #[test] fn decorator_ranges() { - let parse_ast = ast::Suite::parse( + let parse_ast = parse_suite( r#" @my_decorator def test(): @@ -1127,9 +1129,9 @@ class Abcd: } #[test] - fn test_jupyter_magic() { + fn test_ipython_escape_commands() { let parse_ast = parse( - r#" + r" # Normal Python code ( a @@ -1174,7 +1176,7 @@ def foo(): ;foo 1 2 ,foo 1 2 -# Indented magic +# Indented escape commands for a in range(5): !ls @@ -1185,7 +1187,16 @@ foo = %foo \ % foo foo = %foo # comment -"# + +# Help end line magics +foo? +foo.bar?? +foo.bar.baz? +foo[0]?? +foo[0][1]? +foo.bar[0].baz[1]?? +foo.bar[0].baz[2].egg?? +" .trim(), Mode::Jupyter, "", @@ -1195,7 +1206,7 @@ foo = %foo # comment } #[test] - fn test_jupyter_magic_parse_error() { + fn test_ipython_escape_command_parse_error() { let source = r#" a = 1 %timeit a == 1 @@ -1205,7 +1216,7 @@ a = 1 let parse_err = parse_tokens(lxr, Mode::Module, "").unwrap_err(); assert_eq!( parse_err.to_string(), - "line magics are only allowed in Jupyter mode at byte offset 6".to_string() + "IPython escape commands are only allowed in Jupyter mode at byte offset 6".to_string() ); } } diff --git a/crates/ruff_python_parser/src/python.lalrpop b/crates/ruff_python_parser/src/python.lalrpop index 82677be7ca963..7ed8ccbbe295a 100644 --- a/crates/ruff_python_parser/src/python.lalrpop +++ b/crates/ruff_python_parser/src/python.lalrpop @@ -5,15 +5,16 @@ use num_bigint::BigInt; use ruff_text_size::TextSize; -use ruff_python_ast::{self as ast, Ranged, MagicKind}; +use ruff_python_ast::{self as ast, Ranged, IpyEscapeKind}; use crate::{ Mode, lexer::{LexicalError, LexicalErrorType}, - function::{ArgumentList, parse_args, validate_pos_params, validate_arguments}, + function::{ArgumentList, parse_arguments, validate_pos_params, validate_arguments}, context::set_context, string::parse_strings, token::{self, StringKind}, }; +use lalrpop_util::ParseError; grammar(mode: Mode); @@ -88,7 +89,8 @@ SmallStatement: ast::Stmt = { NonlocalStatement, AssertStatement, TypeAliasStatement, - LineMagicStatement, + IpyEscapeCommandStatement, + IpyHelpEndEscapeCommandStatement, }; PassStatement: ast::Stmt = { @@ -153,7 +155,7 @@ ExpressionStatement: ast::Stmt = { AssignSuffix: ast::Expr = { "=" => e, - "=" => e + "=" => e }; TestListOrYieldExpr: ast::Expr = { @@ -321,51 +323,123 @@ AssertStatement: ast::Stmt = { }, }; -LineMagicStatement: ast::Stmt = { - =>? { +IpyEscapeCommandStatement: ast::Stmt = { + =>? { if mode == Mode::Jupyter { - Ok(ast::Stmt::LineMagic( - ast::StmtLineMagic { - kind: m.0, - value: m.1, + Ok(ast::Stmt::IpyEscapeCommand( + ast::StmtIpyEscapeCommand { + kind: c.0, + value: c.1, range: (location..end_location).into() } )) } else { Err(LexicalError { - error: LexicalErrorType::OtherError("line magics are only allowed in Jupyter mode".to_string()), + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), location, })? } } } -LineMagicExpr: ast::Expr = { - =>? { +IpyEscapeCommandExpr: ast::Expr = { + =>? { if mode == Mode::Jupyter { // This should never occur as the lexer won't allow it. - if !matches!(m.0, MagicKind::Magic | MagicKind::Shell) { + if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) { return Err(LexicalError { - error: LexicalErrorType::OtherError("expr line magics are only allowed for % and !".to_string()), + error: LexicalErrorType::OtherError("IPython escape command expr is only allowed for % and !".to_string()), location, })?; } - Ok(ast::Expr::LineMagic( - ast::ExprLineMagic { - kind: m.0, - value: m.1, + Ok(ast::Expr::IpyEscapeCommand( + ast::ExprIpyEscapeCommand { + kind: c.0, + value: c.1, range: (location..end_location).into() } )) } else { Err(LexicalError { - error: LexicalErrorType::OtherError("line magics are only allowed in Jupyter mode".to_string()), + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), location, })? } } } +IpyHelpEndEscapeCommandStatement: ast::Stmt = { + // We are permissive than the original implementation because we would allow whitespace + // between the expression and the suffix while the IPython implementation doesn't allow it. + // For example, `foo ?` would be valid in our case but invalid from IPython. + > =>? { + fn unparse_expr(expr: &ast::Expr, buffer: &mut String) -> Result<(), LexicalError> { + match expr { + ast::Expr::Name(ast::ExprName { id, .. }) => { + buffer.push_str(id.as_str()); + }, + ast::Expr::Subscript(ast::ExprSubscript { value, slice, range, .. }) => { + let ast::Expr::Constant(ast::ExprConstant { value: ast::Constant::Int(integer), .. }) = slice.as_ref() else { + return Err(LexicalError { + error: LexicalErrorType::OtherError("only integer constants are allowed in Subscript expressions in help end escape command".to_string()), + location: range.start(), + }); + }; + unparse_expr(value, buffer)?; + buffer.push('['); + buffer.push_str(&format!("{}", integer)); + buffer.push(']'); + }, + ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { + unparse_expr(value, buffer)?; + buffer.push('.'); + buffer.push_str(attr.as_str()); + }, + _ => { + return Err(LexicalError { + error: LexicalErrorType::OtherError("only Name, Subscript and Attribute expressions are allowed in help end escape command".to_string()), + location: expr.range().start(), + }); + } + } + Ok(()) + } + + if mode != Mode::Jupyter { + return Err(ParseError::User { + error: LexicalError { + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), + location, + }, + }); + } + + let kind = match suffix.len() { + 1 => IpyEscapeKind::Help, + 2 => IpyEscapeKind::Help2, + _ => { + return Err(ParseError::User { + error: LexicalError { + error: LexicalErrorType::OtherError("maximum of 2 `?` tokens are allowed in help end escape command".to_string()), + location, + }, + }); + } + }; + + let mut value = String::new(); + unparse_expr(&e, &mut value)?; + + Ok(ast::Stmt::IpyEscapeCommand( + ast::StmtIpyEscapeCommand { + kind, + value, + range: (location..end_location).into() + } + )) + } +} + CompoundStatement: ast::Stmt = { MatchStatement, IfStatement, @@ -858,11 +932,7 @@ ForStatement: ast::Stmt = { .end(); let target = Box::new(set_context(target, ast::ExprContext::Store)); let iter = Box::new(iter); - if is_async.is_some() { - ast::Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, orelse, range: (location..end_location).into() }) - } else { - ast::Stmt::For(ast::StmtFor { target, iter, body, orelse, range: (location..end_location).into() }) - } + ast::Stmt::For(ast::StmtFor { target, iter, body, orelse, is_async: is_async.is_some(), range: (location..end_location).into() }) }, }; @@ -882,6 +952,7 @@ TryStatement: ast::Stmt = { handlers, orelse, finalbody, + is_star: false, range: (location..end_location).into() }, ) @@ -895,12 +966,13 @@ TryStatement: ast::Stmt = { .map(Ranged::end) .or_else(|| handlers.last().map(Ranged::end)) .unwrap(); - ast::Stmt::TryStar( - ast::StmtTryStar { + ast::Stmt::Try( + ast::StmtTry { body, handlers, orelse, finalbody, + is_star: true, range: (location..end_location).into() }, ) @@ -915,6 +987,7 @@ TryStatement: ast::Stmt = { handlers, orelse, finalbody, + is_star: false, range: (location..end_location).into() }, ) @@ -975,17 +1048,13 @@ ExceptClause: ast::ExceptHandler = { WithStatement: ast::Stmt = { "with" ":" => { let end_location = body.last().unwrap().end(); - if is_async.is_some() { - ast::StmtAsyncWith { items, body, range: (location..end_location).into() }.into() - } else { - ast::StmtWith { items, body, range: (location..end_location).into() }.into() - } + ast::StmtWith { items, body, is_async: is_async.is_some(), range: (location..end_location).into() }.into() }, }; WithItems: Vec = { "(" ","? ")", - "(" ",")?> > >)*> ","? ")" => { + "(" ",")?> >)*> ","? ")" => { left.into_iter().flatten().chain([mid]).chain(right).collect() }, > => vec![<>], @@ -1002,23 +1071,23 @@ WithItemsNoAs: Vec = { } WithItem: ast::WithItem = { - > if Goal != "as" => ast::WithItem { context_expr, optional_vars: None, range: (location..end_location).into() }, + > => ast::WithItem { context_expr, optional_vars: None, range: (location..end_location).into() }, + , +}; + +WithItemAs: ast::WithItem = { > "as" > => { let optional_vars = Some(Box::new(set_context(vars, ast::ExprContext::Store))); ast::WithItem { context_expr, optional_vars, range: (location..end_location).into() } }, -}; +} FuncDef: ast::Stmt = { - "def" " >)?> ":" => { + "def" " >)?> ":" => { let args = Box::new(args); let returns = r.map(Box::new); let end_location = body.last().unwrap().end(); - if is_async.is_some() { - ast::StmtAsyncFunctionDef { name, args, body, decorator_list, returns, type_params: type_params.unwrap_or_default(), range: (location..end_location).into() }.into() - } else { - ast::StmtFunctionDef { name, args, body, decorator_list, returns, type_params: type_params.unwrap_or_default(), range: (location..end_location).into() }.into() - } + ast::StmtFunctionDef { name, parameters:args, body, decorator_list, returns, type_params, is_async: is_async.is_some(), range: (location..end_location).into() }.into() }, }; @@ -1029,25 +1098,25 @@ TypeAliasName: ast::Expr = { } TypeAliasStatement: ast::Stmt = { - "type" "=" > => { + "type" "=" > => { ast::Stmt::TypeAlias( ast::StmtTypeAlias { name: Box::new(name), value: Box::new(value), - type_params: type_params.unwrap_or_default(), + type_params, range: (location..end_location).into() }, ) }, }; -Parameters: ast::Arguments = { +Parameters: ast::Parameters = { "(" )?> ")" =>? { a.as_ref().map(validate_arguments).transpose()?; let range = (location..end_location).into(); let args = a - .map_or_else(|| ast::Arguments::empty(range), |mut arguments| { + .map_or_else(|| ast::Parameters::empty(range), |mut arguments| { arguments.range = range; arguments }); @@ -1058,15 +1127,15 @@ Parameters: ast::Arguments = { // Note that this is a macro which is used once for function defs, and // once for lambda defs. -ParameterList: ast::Arguments = { - > >)?> ","? =>? { +ParameterList: ast::Parameters = { + > >)?> ","? =>? { validate_pos_params(¶m1)?; let (posonlyargs, args) = param1; // Now gather rest of parameters: let (vararg, kwonlyargs, kwarg) = args2.unwrap_or((None, vec![], None)); - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -1075,7 +1144,7 @@ ParameterList: ast::Arguments = { range: (location..end_location).into() }) }, - > >)> ","? =>? { + > >)> ","? =>? { validate_pos_params(¶m1)?; let (posonlyargs, args) = param1; @@ -1084,7 +1153,7 @@ ParameterList: ast::Arguments = { let kwonlyargs = vec![]; let kwarg = kw; - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -1093,9 +1162,9 @@ ParameterList: ast::Arguments = { range: (location..end_location).into() }) }, - > ","? => { + > ","? => { let (vararg, kwonlyargs, kwarg) = params; - ast::Arguments { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs, @@ -1104,8 +1173,8 @@ ParameterList: ast::Arguments = { range: (location..end_location).into() } }, - > ","? => { - ast::Arguments { + > ","? => { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs: vec![], @@ -1118,61 +1187,61 @@ ParameterList: ast::Arguments = { // Use inline here to make sure the "," is not creating an ambiguity. #[inline] -ParameterDefs: (Vec, Vec) = { - >> => { +ParameterDefs: (Vec, Vec) = { + >> => { (vec![], args) }, - >> "," "/" >)*> => { + >> "," "/" >)*> => { (posonlyargs, args) }, }; -ParameterDef: ast::ArgWithDefault = { - => i, - "=" > => { +ParameterDef: ast::ParameterWithDefault = { + => i, + "=" > => { i.default = Some(Box::new(e)); i.range = (i.range.start()..end_location).into(); i }, }; -UntypedParameter: ast::ArgWithDefault = { +UntypedParameter: ast::ParameterWithDefault = { => { - let def = ast::Arg { arg, annotation: None, range: (location..end_location).into() }; - ast::ArgWithDefault { def, default: None, range: (location..end_location).into() } + let def = ast::Parameter { name:arg, annotation: None, range: (location..end_location).into() }; + ast::ParameterWithDefault { parameter:def, default: None, range: (location..end_location).into() } }, }; -StarUntypedParameter: ast::Arg = { - => ast::Arg { arg, annotation: None, range: (location..end_location).into() }, +StarUntypedParameter: ast::Parameter = { + => ast::Parameter { name:arg, annotation: None, range: (location..end_location).into() }, }; -TypedParameter: ast::ArgWithDefault = { +TypedParameter: ast::ParameterWithDefault = { >)?> => { let annotation = a.map(Box::new); - let def = ast::Arg { arg, annotation, range: (location..end_location).into() }; - ast::ArgWithDefault { def, default: None, range: (location..end_location).into() } + let def = ast::Parameter { name:arg, annotation, range: (location..end_location).into() }; + ast::ParameterWithDefault { parameter:def, default: None, range: (location..end_location).into() } }, }; -StarTypedParameter: ast::Arg = { +StarTypedParameter: ast::Parameter = { )?> => { let annotation = a.map(Box::new); - ast::Arg { arg, annotation, range: (location..end_location).into() } + ast::Parameter { name:arg, annotation, range: (location..end_location).into() } }, }; -DoubleStarTypedParameter: ast::Arg = { +DoubleStarTypedParameter: ast::Parameter = { >)?> => { let annotation = a.map(Box::new); - ast::Arg { arg, annotation, range: (location..end_location).into() } + ast::Parameter { name:arg, annotation, range: (location..end_location).into() } }, }; // Use inline here to make sure the "," is not creating an ambiguity. // TODO: figure out another grammar that makes this inline no longer required. #[inline] -ParameterListStarArgs: (Option>, Vec, Option>) = { - "*" >)*> >)?> =>? { +ParameterListStarArgs: (Option>, Vec, Option>) = { + "*" >)*> >)?> =>? { if va.is_none() && kwonlyargs.is_empty() && kwarg.is_none() { return Err(LexicalError { error: LexicalErrorType::OtherError("named arguments must follow bare *".to_string()), @@ -1187,37 +1256,34 @@ ParameterListStarArgs: (Option: Option> = { - "**" => { +KwargParameter: Option> = { + "**" => { kwarg.map(Box::new) } }; ClassDef: ast::Stmt = { - "class" ":" => { - let (bases, keywords) = match a { - Some((_, arg, _)) => (arg.args, arg.keywords), - None => (vec![], vec![]), - }; + "class" ":" => { let end_location = body.last().unwrap().end(); ast::Stmt::ClassDef( ast::StmtClassDef { name, - bases, - keywords, + arguments: arguments.map(Box::new), body, decorator_list, - type_params: type_params.unwrap_or_default(), + type_params: type_params.map(Box::new), range: (location..end_location).into() }, ) }, }; - -TypeParamList: Vec = { +TypeParams: ast::TypeParams = { "[" > ","? "]" => { - vars + ast::TypeParams { + type_params: vars, + range: (location..end_location).into() + } } }; @@ -1273,29 +1339,31 @@ NamedExpressionTest: ast::Expr = { Test<"all">, } +NamedExpressionName: ast::Expr = { + => ast::Expr::Name( + ast::ExprName { id: id.into(), ctx: ast::ExprContext::Store, range: (location..end_location).into() }, + ), +} + NamedExpression: ast::Expr = { - ":=" > => { + ":=" > => { ast::Expr::NamedExpr( ast::ExprNamedExpr { - target: Box::new(ast::Expr::Name( - ast::ExprName { id: id.into(), ctx: ast::ExprContext::Store, range: (location..end_location).into() }, - )), - range: (location..value.end()).into(), + target: Box::new(target), value: Box::new(value), + range: (location..end_location).into(), } ) }, }; LambdaDef: ast::Expr = { - "lambda" ?> ":" > =>? { - p.as_ref().map(validate_arguments).transpose()?; - let p = p - .unwrap_or_else(|| ast::Arguments::empty((location_args..end_location_args).into())); + "lambda" ?> ":" > =>? { + parameters.as_ref().map(validate_arguments).transpose()?; Ok(ast::Expr::Lambda( ast::ExprLambda { - args: Box::new(p), + parameters: parameters.map(Box::new), body: Box::new(body), range: (location..end_location).into() } @@ -1444,9 +1512,9 @@ AtomExpr: ast::Expr = { AtomExpr2: ast::Expr = { Atom, - > "(" ")" => { + > => { ast::Expr::Call( - ast::ExprCall { func: Box::new(f), args: a.args, keywords: a.keywords, range: (location..end_location).into() } + ast::ExprCall { func: Box::new(f), arguments, range: (location..end_location).into() } ) }, > "[" "]" => ast::Expr::Subscript( @@ -1663,10 +1731,14 @@ SingleForComprehension: ast::Comprehension = { ExpressionNoCond: ast::Expr = OrTest<"all">; ComprehensionIf: ast::Expr = "if" => c; -ArgumentList: ArgumentList = { - > =>? { - let arg_list = parse_args(e)?; - Ok(arg_list) +Arguments: ast::Arguments = { + "(" > ")" =>? { + let ArgumentList { args, keywords } = parse_arguments(e)?; + Ok(ast::Arguments { + args, + keywords, + range: (location..end_location).into() + }) } }; @@ -1743,6 +1815,7 @@ extern { Dedent => token::Tok::Dedent, StartModule => token::Tok::StartModule, StartExpression => token::Tok::StartExpression, + "?" => token::Tok::Question, "+" => token::Tok::Plus, "-" => token::Tok::Minus, "~" => token::Tok::Tilde, @@ -1836,8 +1909,8 @@ extern { triple_quoted: }, name => token::Tok::Name { name: }, - line_magic => token::Tok::MagicCommand { - kind: , + ipy_escape_command => token::Tok::IpyEscapeCommand { + kind: , value: }, "\n" => token::Tok::Newline, diff --git a/crates/ruff_python_parser/src/python.rs b/crates/ruff_python_parser/src/python.rs index b85ec359f4a79..d736d0f7ce7fd 100644 --- a/crates/ruff_python_parser/src/python.rs +++ b/crates/ruff_python_parser/src/python.rs @@ -1,16 +1,17 @@ // auto-generated: "lalrpop 0.20.0" -// sha3: 5eea4e365b6d7ea02f64f350bf973830a71442f4690d98e9a286c2a03b5260cc +// sha3: fc07b64fd8599f77540f3e4cb78df0895813bcfc75a952c8ed36df309e2dded7 use num_bigint::BigInt; use ruff_text_size::TextSize; -use ruff_python_ast::{self as ast, Ranged, MagicKind}; +use ruff_python_ast::{self as ast, Ranged, IpyEscapeKind}; use crate::{ Mode, lexer::{LexicalError, LexicalErrorType}, - function::{ArgumentList, parse_args, validate_pos_params, validate_arguments}, + function::{ArgumentList, parse_arguments, validate_pos_params, validate_arguments}, context::set_context, string::parse_strings, token::{self, StringKind}, }; +use lalrpop_util::ParseError; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; #[allow(unused_imports)] @@ -24,15 +25,16 @@ mod __parse__Top { use num_bigint::BigInt; use ruff_text_size::TextSize; - use ruff_python_ast::{self as ast, Ranged, MagicKind}; + use ruff_python_ast::{self as ast, Ranged, IpyEscapeKind}; use crate::{ Mode, lexer::{LexicalError, LexicalErrorType}, - function::{ArgumentList, parse_args, validate_pos_params, validate_arguments}, + function::{ArgumentList, parse_arguments, validate_pos_params, validate_arguments}, context::set_context, string::parse_strings, token::{self, StringKind}, }; + use lalrpop_util::ParseError; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; #[allow(unused_imports)] @@ -47,2429 +49,2421 @@ mod __parse__Top { Variant1((f64, f64)), Variant2(f64), Variant3(BigInt), - Variant4((MagicKind, String)), + Variant4((IpyEscapeKind, String)), Variant5(String), Variant6((String, StringKind, bool)), Variant7(core::option::Option), - Variant8((token::Tok, ArgumentList, token::Tok)), - Variant9(core::option::Option<(token::Tok, ArgumentList, token::Tok)>), - Variant10(Option>), - Variant11(core::option::Option>>), - Variant12(ast::ArgWithDefault), - Variant13(alloc::vec::Vec), - Variant14((Option>, Vec, Option>)), - Variant15(core::option::Option<(Option>, Vec, Option>)>), - Variant16(ast::Expr), - Variant17(core::option::Option), - Variant18(alloc::vec::Vec), - Variant19(ast::WithItem), - Variant20(alloc::vec::Vec), - Variant21((token::Tok, ast::Identifier)), - Variant22(alloc::vec::Vec<(token::Tok, ast::Identifier)>), - Variant23(alloc::vec::Vec), - Variant24(ast::Identifier), - Variant25(core::option::Option), - Variant26(ast::Suite), - Variant27(core::option::Option), - Variant28((TextSize, ast::Expr, ast::Suite)), - Variant29(alloc::vec::Vec<(TextSize, ast::Expr, ast::Suite)>), - Variant30((TextSize, ast::Suite)), - Variant31(core::option::Option<(TextSize, ast::Suite)>), - Variant32((Option<(TextSize, TextSize, Option)>, ast::Expr)), - Variant33(alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), - Variant34(Vec), - Variant35(core::option::Option>), - Variant36(ast::Pattern), - Variant37(alloc::vec::Vec), - Variant38(ast::Stmt), - Variant39(alloc::vec::Vec), - Variant40((ast::Expr, ast::Identifier)), - Variant41(Vec), - Variant42(core::option::Option>), - Variant43((TextSize, (String, StringKind, bool), TextSize)), - Variant44(alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>), - Variant45((ast::CmpOp, ast::Expr)), - Variant46(alloc::vec::Vec<(ast::CmpOp, ast::Expr)>), - Variant47(ast::Arguments), - Variant48(core::option::Option), - Variant49(TextSize), - Variant50(ast::Operator), - Variant51(ArgumentList), - Variant52(Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), - Variant53(Vec), - Variant54(Vec), - Variant55(core::option::Option>), - Variant56(ast::CmpOp), - Variant57(ast::Constant), - Variant58(ast::Decorator), - Variant59(alloc::vec::Vec), - Variant60((Option>, ast::Expr)), - Variant61((ast::Expr, ast::Expr)), - Variant62(Vec<(Option>, ast::Expr)>), - Variant63(core::option::Option>, ast::Expr)>>), - Variant64(ast::Arg), - Variant65(core::option::Option), - Variant66(ast::ExceptHandler), - Variant67(alloc::vec::Vec), - Variant68(core::option::Option<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), - Variant69(ast::Alias), - Variant70(Vec), - Variant71(ast::Int), - Variant72(alloc::vec::Vec), - Variant73((Option, Option)), - Variant74(ast::MatchCase), - Variant75(alloc::vec::Vec), - Variant76((ast::Identifier, ast::Pattern)), - Variant77((ast::Expr, ast::Pattern)), - Variant78(Vec), - Variant79(Vec<(ast::Identifier, ast::Pattern)>), - Variant80(Vec<(ast::Expr, ast::Pattern)>), - Variant81(Vec), - Variant82(Vec), - Variant83((Vec, Vec)), - Variant84(core::option::Option), - Variant85(ast::Comprehension), - Variant86(alloc::vec::Vec), - Variant87(Option), - Variant88(core::option::Option>), - Variant89(Vec), - Variant90(ast::Mod), - Variant91(ast::TypeParam), - Variant92(core::option::Option>), + Variant8(Option>), + Variant9(core::option::Option>>), + Variant10(ast::ParameterWithDefault), + Variant11(alloc::vec::Vec), + Variant12((Option>, Vec, Option>)), + Variant13(core::option::Option<(Option>, Vec, Option>)>), + Variant14(ast::Expr), + Variant15(core::option::Option), + Variant16(alloc::vec::Vec), + Variant17(ast::WithItem), + Variant18(alloc::vec::Vec), + Variant19((token::Tok, ast::Identifier)), + Variant20(alloc::vec::Vec<(token::Tok, ast::Identifier)>), + Variant21(alloc::vec::Vec), + Variant22(ast::Identifier), + Variant23(core::option::Option), + Variant24(ast::Suite), + Variant25(core::option::Option), + Variant26((TextSize, ast::Expr, ast::Suite)), + Variant27(alloc::vec::Vec<(TextSize, ast::Expr, ast::Suite)>), + Variant28((TextSize, ast::Suite)), + Variant29(core::option::Option<(TextSize, ast::Suite)>), + Variant30((Option<(TextSize, TextSize, Option)>, ast::Expr)), + Variant31(alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), + Variant32(Vec), + Variant33(core::option::Option>), + Variant34(ast::Pattern), + Variant35(alloc::vec::Vec), + Variant36(ast::Stmt), + Variant37(alloc::vec::Vec), + Variant38((ast::Expr, ast::Identifier)), + Variant39(Vec), + Variant40(core::option::Option>), + Variant41((TextSize, (String, StringKind, bool), TextSize)), + Variant42(alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>), + Variant43((ast::CmpOp, ast::Expr)), + Variant44(alloc::vec::Vec<(ast::CmpOp, ast::Expr)>), + Variant45(ast::Parameters), + Variant46(core::option::Option), + Variant47(TextSize), + Variant48(ast::Operator), + Variant49(ast::Arguments), + Variant50(core::option::Option), + Variant51(Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), + Variant52(Vec), + Variant53(Vec), + Variant54(core::option::Option>), + Variant55(ast::CmpOp), + Variant56(ast::Constant), + Variant57(ast::Decorator), + Variant58(alloc::vec::Vec), + Variant59((Option>, ast::Expr)), + Variant60((ast::Expr, ast::Expr)), + Variant61(Vec<(Option>, ast::Expr)>), + Variant62(core::option::Option>, ast::Expr)>>), + Variant63(ast::Parameter), + Variant64(core::option::Option), + Variant65(ast::ExceptHandler), + Variant66(alloc::vec::Vec), + Variant67(core::option::Option<(Option<(TextSize, TextSize, Option)>, ast::Expr)>), + Variant68(ast::Alias), + Variant69(Vec), + Variant70(ast::Int), + Variant71(alloc::vec::Vec), + Variant72((Option, Option)), + Variant73(ast::MatchCase), + Variant74(alloc::vec::Vec), + Variant75((ast::Identifier, ast::Pattern)), + Variant76((ast::Expr, ast::Pattern)), + Variant77(Vec), + Variant78(Vec<(ast::Identifier, ast::Pattern)>), + Variant79(Vec<(ast::Expr, ast::Pattern)>), + Variant80(Vec), + Variant81(Vec), + Variant82((Vec, Vec)), + Variant83(core::option::Option), + Variant84(ast::Comprehension), + Variant85(alloc::vec::Vec), + Variant86(Option), + Variant87(core::option::Option>), + Variant88(Vec), + Variant89(ast::Mod), + Variant90(ast::TypeParam), + Variant91(ast::TypeParams), + Variant92(core::option::Option), Variant93(ast::UnaryOp), } const __ACTION: &[i16] = &[ // State 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, // State 1 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 2 - -744, 0, 0, 0, 0, 0, -744, 0, -744, 0, 0, 0, -744, 0, 0, -744, 0, 0, 0, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -744, 0, -744, -744, -744, -744, 0, 0, 0, 0, 0, -744, -744, -744, -744, 0, -744, -744, -744, -744, 0, 0, 0, 0, -744, -744, -744, -744, -744, 0, 0, -744, -744, -744, -744, 0, -744, -744, -744, -744, -744, -744, -744, -744, -744, 0, 0, 0, -744, 0, 0, 0, 0, -744, -744, -744, -744, -744, -744, + -748, 0, 0, 0, 0, 0, -748, 0, -748, 0, 0, 0, -748, 0, 0, -748, 0, 0, 0, -748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -748, 0, -748, -748, -748, -748, 0, 0, 0, 0, 0, -748, -748, -748, -748, 0, -748, -748, -748, -748, 0, 0, 0, 0, -748, -748, -748, -748, -748, 0, 0, -748, -748, -748, -748, 0, -748, -748, -748, -748, -748, -748, -748, -748, -748, 0, 0, 0, -748, 0, 0, 0, 0, -748, -748, -748, -748, -748, -748, // State 3 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 4 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 5 - -766, -766, 0, -766, -766, -766, 0, -766, 0, 0, -766, -766, 427, -766, -766, 428, -766, 0, 0, 0, 0, 0, -766, -766, -766, 0, -766, -766, -766, -766, -766, -766, -766, -766, -766, -766, -766, 0, -766, 0, 0, 0, 0, -766, -766, -766, -766, -766, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, -766, -766, 0, -766, 0, -766, -766, 0, 0, 0, -766, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, -766, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -770, -770, 0, -770, -770, -770, 0, -770, 0, 0, -770, -770, 426, -770, -770, 427, -770, 0, 0, 0, 0, 0, -770, -770, -770, 0, -770, -770, -770, -770, -770, -770, -770, -770, -770, -770, -770, -770, 0, -770, 0, 0, 0, 0, -770, -770, -770, -770, -770, 0, -770, 0, 0, 0, 0, 0, 0, 0, 0, -770, 0, 0, -770, -770, 0, -770, 0, -770, -770, 0, 0, 0, -770, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, -770, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 6 - -315, 429, 0, -315, 0, -315, 0, -315, 0, 0, -315, -315, 0, -315, -315, 0, -315, 0, 0, 0, 0, 0, -315, -315, -315, 0, -315, 430, 0, -315, 431, -315, 432, 433, 434, 0, -315, 0, -315, 0, 0, 0, 0, -315, 0, -315, -315, -315, 0, -315, 0, 0, 0, 0, 0, 0, 0, 0, -315, 0, 0, -315, -315, 0, -315, 0, 435, 436, 0, 0, 0, 437, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, -315, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -249, -249, -249, -249, -249, -249, 23, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, 0, 24, 0, -249, -249, -249, -249, -249, 0, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, -249, 0, 0, 0, 25, -249, -249, -249, -249, -249, 0, -249, 0, 0, 0, 0, 0, 0, 0, 0, -249, 0, 0, -249, -249, 0, -249, 0, -249, -249, 0, 0, 0, -249, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, -249, -249, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 7 - 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -317, 429, 0, -317, 0, -317, 0, -317, 0, 0, -317, -317, 0, -317, -317, 0, -317, 0, 0, 0, 0, 0, -317, -317, -317, 0, -317, 430, 0, -317, 431, -317, 432, 433, 434, 0, -317, 0, 0, -317, 0, 0, 0, 0, -317, 0, -317, -317, -317, 0, -317, 0, 0, 0, 0, 0, 0, 0, 0, -317, 0, 0, -317, -317, 0, -317, 0, 435, 436, 0, 0, 0, 437, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, -317, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 8 - -156, -156, 0, -156, -156, -156, 0, -156, 0, 0, -156, -156, 0, -156, -156, 0, -156, 0, 0, 0, 0, 0, -156, -156, -156, 0, -156, -156, 441, -156, -156, -156, -156, -156, -156, 442, -156, 0, -156, 0, 0, 0, 0, -156, -156, -156, -156, -156, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, -156, -156, 0, -156, 0, -156, -156, 0, 0, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 9 - -168, -168, 443, -168, -168, -168, 0, -168, 444, 0, -168, -168, -168, -168, -168, -168, -168, 0, 0, 0, 445, 446, -168, -168, -168, 0, -168, -168, -168, -168, -168, -168, -168, -168, -168, -168, -168, 447, -168, 0, 0, 0, 0, -168, -168, -168, -168, -168, 0, -168, 0, 0, 0, 0, 0, 0, 0, 0, -168, 0, 0, -168, -168, 0, -168, 0, -168, -168, 0, 0, 0, -168, -168, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168, -168, -168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -156, -156, 0, -156, -156, -156, 0, -156, 0, 0, -156, -156, 0, -156, -156, 0, -156, 0, 0, 0, 0, 0, -156, -156, -156, 0, -156, -156, 441, -156, -156, -156, -156, -156, -156, 442, -156, -156, 0, -156, 0, 0, 0, 0, -156, -156, -156, -156, -156, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, -156, -156, 0, -156, 0, -156, -156, 0, 0, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 10 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -170, -170, 443, -170, -170, -170, 0, -170, 444, 0, -170, -170, -170, -170, -170, -170, -170, 0, 0, 0, 445, 446, -170, -170, -170, 0, -170, -170, -170, -170, -170, -170, -170, -170, -170, -170, -170, -170, 447, -170, 0, 0, 0, 0, -170, -170, -170, -170, -170, 0, -170, 0, 0, 0, 0, 0, 0, 0, 0, -170, 0, 0, -170, -170, 0, -170, 0, -170, -170, 0, 0, 0, -170, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, -170, -170, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 11 - 0, 0, 0, 0, 0, 0, 12, 455, 13, 36, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 12 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 456, 14, 37, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 13 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 463, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 14 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 464, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 15 - 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 16 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 17 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 44, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 479, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 18 - 504, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 505, 15, 506, 0, 50, 507, 51, 52, 0, 0, 0, 0, 53, 54, 55, 56, 57, 0, 0, 16, 58, 59, 17, 0, 508, 60, 61, 509, 62, 63, 64, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 46, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 479, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 19 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 505, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 506, 16, 507, 0, 53, 508, 54, 55, 0, 0, 0, 0, 56, 57, 58, 59, 60, 0, 0, 17, 61, 62, 18, 0, 509, 63, 64, 510, 65, 66, 67, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 20 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 21 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 22 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 516, 72, 73, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 23 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 24 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 25 - -314, 429, 0, -314, 0, -314, 0, -314, 0, 0, -314, -314, 0, -314, -314, 0, -314, 0, 0, 0, 0, 0, -314, -314, -314, 0, -314, 430, 0, -314, 431, -314, 432, 433, 434, 0, -314, 0, -314, 0, 0, 0, 0, -314, 0, -314, -314, -314, 0, -314, 0, 0, 0, 0, 0, 0, 0, 0, -314, 0, 0, -314, -314, 0, -314, 0, 435, 436, 0, 0, 0, 437, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 26 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -316, 429, 0, -316, 0, -316, 0, -316, 0, 0, -316, -316, 0, -316, -316, 0, -316, 0, 0, 0, 0, 0, -316, -316, -316, 0, -316, 430, 0, -316, 431, -316, 432, 433, 434, 0, -316, 0, 0, -316, 0, 0, 0, 0, -316, 0, -316, -316, -316, 0, -316, 0, 0, 0, 0, 0, 0, 0, 0, -316, 0, 0, -316, -316, 0, -316, 0, 435, 436, 0, 0, 0, 437, -316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -316, -316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 27 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 28 - -419, 0, 0, -419, 0, -419, 12, -419, 13, 0, -419, -419, 411, -419, 0, 412, -419, 0, 0, 413, 0, 0, -419, -419, -419, 0, -419, 0, 0, -419, 0, -419, 0, 0, 0, 0, -419, 0, -419, 414, 415, 416, 14, 0, 0, -419, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, -419, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 29 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -421, 0, 0, -421, 0, -421, 13, -421, 14, 0, -421, -421, 410, -421, 0, 411, -421, 0, 0, 412, 0, 0, -421, -421, -421, 0, -421, 0, 0, -421, 0, -421, 0, 0, 0, 0, -421, 0, 0, -421, 413, 414, 415, 15, 0, 0, -421, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, -421, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 30 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 31 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 32 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 33 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 34 - 0, 0, 0, 0, 0, 0, 0, 536, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 35 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 537, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 36 - -915, 0, 0, 0, 0, 0, 12, -915, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, -915, 0, 0, 0, 0, -915, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 37 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -920, 0, 0, 0, 0, 0, 13, -920, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, -920, 0, 0, 0, 0, -920, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 38 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, -706, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 39 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -450, 0, 0, 0, 0, 0, 0, 0, 0, 0, -450, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + -248, -248, -248, -248, -248, -248, 23, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, 0, 24, 0, -248, -248, -248, -248, -248, 0, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, -248, 0, 0, 0, 25, -248, -248, -248, -248, -248, 0, -248, 0, 0, 0, 0, 0, 0, 0, 0, -248, 0, 0, -248, -248, 0, -248, 0, -248, -248, 0, 0, 0, -248, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, -248, -248, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 40 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, -710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 41 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 42 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 43 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 44 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 45 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 555, 0, 0, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 46 - -375, 0, 0, 557, 0, 558, 0, 0, 0, 0, 559, 560, 0, 561, 0, 0, 562, 0, 0, 0, 0, 0, 563, 564, 0, 0, -375, 0, 0, 565, 0, 93, 0, 0, 0, 0, 566, 0, 567, 0, 0, 0, 0, 0, 0, 568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 569, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 47 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 556, 0, 0, 0, 92, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 48 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -317, 429, 0, -317, 0, -317, 0, 0, 0, 0, -317, -317, 0, -317, -317, 0, -317, 0, 0, 0, 0, 0, -317, -317, -317, 0, -317, 430, 0, -317, 431, -317, 432, 433, 434, 0, -317, 558, 0, -317, 0, 0, 0, 0, 0, 0, -317, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, 0, 435, 436, 0, 0, 0, 437, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 49 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + -377, 0, 0, 560, 0, 561, 0, 0, 0, 0, 562, 563, 0, 564, 0, 0, 565, 0, 0, 0, 0, 0, 566, 567, 0, 0, -377, 0, 0, 568, 0, 96, 0, 0, 0, 0, 569, 0, 0, 570, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 572, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 50 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 51 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 52 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 53 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 585, 586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 54 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 55 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 56 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 588, 589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, // State 57 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 58 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 59 - -751, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, -751, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, // State 60 - -387, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, -387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 61 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 62 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -755, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 63 - 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 628, 629, 630, 113, 0, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -389, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, -389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 64 - -155, -155, 0, -155, -155, -155, 0, -155, 0, 0, -155, -155, 0, -155, -155, 0, -155, 0, 0, 0, 0, 0, -155, -155, -155, 0, -155, -155, 441, -155, -155, -155, -155, -155, -155, 442, -155, 0, -155, 0, 0, 0, 0, -155, -155, -155, -155, -155, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, -155, -155, 0, -155, 0, -155, -155, 0, 0, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 65 - -167, -167, 443, -167, -167, -167, 0, -167, 444, 0, -167, -167, -167, -167, -167, -167, -167, 0, 0, 0, 445, 446, -167, -167, -167, 0, -167, -167, -167, -167, -167, -167, -167, -167, -167, -167, -167, 447, -167, 0, 0, 0, 0, -167, -167, -167, -167, -167, 0, -167, 0, 0, 0, 0, 0, 0, 0, 0, -167, 0, 0, -167, -167, 0, -167, 0, -167, -167, 0, 0, 0, -167, -167, 0, 0, 0, 0, 0, 0, 0, 0, 0, -167, -167, -167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 66 - 0, 0, 0, 0, 0, 0, 12, -166, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 631, 632, 633, 117, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 67 - 0, 0, 0, 0, 0, 0, 0, -411, 0, 0, 0, 0, 0, 0, -411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -155, -155, 0, -155, -155, -155, 0, -155, 0, 0, -155, -155, 0, -155, -155, 0, -155, 0, 0, 0, 0, 0, -155, -155, -155, 0, -155, -155, 441, -155, -155, -155, -155, -155, -155, 442, -155, -155, 0, -155, 0, 0, 0, 0, -155, -155, -155, -155, -155, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, -155, -155, 0, -155, 0, -155, -155, 0, 0, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 68 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -169, -169, 443, -169, -169, -169, 0, -169, 444, 0, -169, -169, -169, -169, -169, -169, -169, 0, 0, 0, 445, 446, -169, -169, -169, 0, -169, -169, -169, -169, -169, -169, -169, -169, -169, -169, -169, -169, 447, -169, 0, 0, 0, 0, -169, -169, -169, -169, -169, 0, -169, 0, 0, 0, 0, 0, 0, 0, 0, -169, 0, 0, -169, -169, 0, -169, 0, -169, -169, 0, 0, 0, -169, -169, 0, 0, 0, 0, 0, 0, 0, 0, 0, -169, -169, -169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 69 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 635, 72, 73, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 70 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, -818, 412, 0, 0, 0, 413, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -818, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -413, 0, 0, 0, 0, 0, 0, -413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 71 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 72 - -765, -765, 0, -765, -765, -765, 0, -765, 0, 0, -765, -765, 427, -765, -765, 428, -765, 0, 0, 0, 0, 0, -765, -765, -765, 0, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, 0, -765, 0, 0, 0, 0, -765, -765, -765, -765, -765, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, -765, -765, 0, -765, 0, -765, -765, 0, 0, 0, -765, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, -765, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 73 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, -823, 411, 0, 0, 0, 412, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -823, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 74 - 0, 0, 0, 0, 0, 0, 0, -301, 0, 0, 0, 0, 0, 0, -301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -301, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 75 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -769, -769, 0, -769, -769, -769, 0, -769, 0, 0, -769, -769, 426, -769, -769, 427, -769, 0, 0, 0, 0, 0, -769, -769, -769, 0, -769, -769, -769, -769, -769, -769, -769, -769, -769, -769, -769, -769, 0, -769, 0, 0, 0, 0, -769, -769, -769, -769, -769, 0, -769, 0, 0, 0, 0, 0, 0, 0, 0, -769, 0, 0, -769, -769, 0, -769, 0, -769, -769, 0, 0, 0, -769, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, -769, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 76 - 0, 0, 0, 0, 0, 0, 12, 646, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 77 - 0, 0, 0, 0, 0, 0, 12, 649, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -303, 0, 0, 0, 0, 0, 0, -303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -303, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 78 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 79 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -455, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 650, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 80 - 0, 0, 0, 0, 0, 0, 0, 0, 127, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, -657, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 653, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 81 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 82 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -458, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 83 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, -705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 131, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, -661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 84 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -698, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 85 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 44, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, -346, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 86 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, -763, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, -709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 87 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 88 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 46, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, -348, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 89 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, -767, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 90 - -376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -376, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 91 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 92 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 675, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 93 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -378, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 94 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 95 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 680, 420, 421, // State 96 - 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 628, 629, 630, 113, 0, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 97 - 0, 0, 0, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 98 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 99 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 585, 586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 631, 632, 633, 117, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 100 - -350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -350, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, -350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 101 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 102 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 588, 589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, // State 103 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 104 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 105 - 0, -766, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 427, 0, -766, 428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, -766, 0, -766, 0, -766, -766, -766, -766, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, -766, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, -766, -766, 0, 0, 0, -766, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 106 - 0, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 430, 0, 0, 431, 0, 432, 433, 434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -315, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -315, 0, 435, 436, 0, 0, 0, 437, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 107 - 0, -156, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 441, 0, -156, 0, -156, -156, -156, 442, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, -156, -156, 0, 0, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 108 - 0, -168, 443, 0, -168, 0, 0, 0, 444, 0, 0, 0, -168, 0, -168, -168, 0, 0, 0, 0, 445, 446, 0, 0, 0, 0, 0, -168, -168, 0, -168, 0, -168, -168, -168, -168, 0, 447, 0, 0, 0, 0, 0, 0, -168, 0, -168, -168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168, 0, -168, -168, 0, 0, 0, -168, -168, 0, 0, 0, 0, 0, 0, 0, 0, 0, -168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -770, 0, 0, -770, 0, 0, 0, 0, 0, 0, 0, 426, 0, -770, 427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, -770, 0, -770, 0, -770, -770, -770, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, 0, -770, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, 0, -770, -770, 0, 0, 0, -770, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 109 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -249, -249, 0, -249, 0, 23, 0, -249, -249, 0, 0, -249, 0, -249, -249, 0, 0, 164, 0, -249, -249, 0, 0, 0, 0, 0, -249, -249, 0, -249, 0, -249, -249, -249, -249, 0, 0, -249, 0, 0, 0, 0, 165, 0, -249, 0, -249, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -249, 0, -249, -249, 0, 0, 0, -249, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 110 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 430, 0, 0, 431, 0, 432, 433, 434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, 0, 435, 436, 0, 0, 0, 437, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 111 - 0, 0, 0, 0, 0, 0, 12, 697, 13, 176, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -156, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 441, 0, -156, 0, -156, -156, -156, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, -156, -156, 0, 0, 0, -156, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 112 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 699, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -170, 443, 0, -170, 0, 0, 0, 444, 0, 0, 0, -170, 0, -170, -170, 0, 0, 0, 0, 445, 446, 0, 0, 0, 0, 0, -170, -170, 0, -170, 0, -170, -170, -170, -170, 0, 0, 447, 0, 0, 0, 0, 0, 0, -170, 0, -170, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -170, 0, -170, -170, 0, 0, 0, -170, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 113 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 114 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 115 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 44, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 704, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 703, 14, 179, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 116 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 705, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 117 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -820, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 118 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, -816, 412, 0, 0, 0, 413, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -816, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 119 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -821, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 46, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 709, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 120 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 121 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, -778, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, -778, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -825, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 122 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, -821, 411, 0, 0, 0, 412, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -821, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 123 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -826, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 124 - 0, 0, 0, 0, 0, 0, 12, 715, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 125 - 0, 0, 0, 0, 0, 0, 0, 717, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, -782, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, -782, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 126 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 127 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, -685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 128 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 721, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 129 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -697, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 723, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 130 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, -679, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 131 - 0, 0, 0, 0, 0, 0, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, -689, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 132 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 133 - -379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -379, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 134 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 135 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 136 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 137 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + -381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -381, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 138 - 0, 0, 0, 0, 0, 0, 0, 0, 196, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 139 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 140 - 0, 0, 0, 0, 0, 0, 0, 743, 200, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 141 - -370, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, -370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 142 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 200, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 143 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -417, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 144 - 0, 0, 0, 0, 0, 0, 202, 0, 749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 749, 204, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 145 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + -372, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 146 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 147 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 148 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 206, 0, 755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 149 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 150 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 151 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 152 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 153 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, // State 154 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 155 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 156 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 157 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 158 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 159 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 160 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 161 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 162 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 163 - 0, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, -316, 0, 0, 430, 0, 0, 431, 0, 432, 433, 434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, 0, 435, 436, 0, 0, 0, 437, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 164 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 165 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 166 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -316, 0, 0, 0, 0, 0, 0, 0, 0, 0, -318, 0, 0, 430, 0, 0, 431, 0, 432, 433, 434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -316, -316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -316, 0, 435, 436, 0, 0, 0, 437, -316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 167 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 168 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 169 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 170 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 171 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 172 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 173 - 0, 0, 0, 0, 0, 0, 0, 783, 0, 0, 0, 0, 0, 0, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 174 - 0, 0, 0, 0, 0, 0, 0, 786, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 175 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 176 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 788, 0, 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 177 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 791, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 178 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 179 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 180 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -248, -248, 0, -248, 0, 23, 0, -248, -248, 0, 0, -248, 0, -248, -248, 0, 0, 24, 0, -248, -248, 0, 0, -250, 0, 0, -248, -248, 0, -248, 0, -248, -248, -248, -248, 0, 0, -248, 0, 0, 0, 0, 25, 0, -248, 0, -248, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -248, 0, -248, -248, 0, 0, 0, -248, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 181 - 0, 0, 0, 0, 0, 0, 12, 797, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 182 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, -672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 183 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 184 - 0, 0, 0, 0, 0, 0, 0, 0, 224, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 185 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 802, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 186 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0, -676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 187 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 188 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 227, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 189 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 190 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 191 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 192 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 193 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 194 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 195 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 196 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 197 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 198 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 199 - 0, 0, 0, 0, 0, 0, 0, -628, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 200 - 0, 0, 0, 0, 0, 0, 0, -448, 0, 0, 0, 0, 0, 0, -448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 201 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 202 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 203 - -425, 0, 0, 0, 0, 0, -425, 0, -425, 0, 0, 0, -425, 0, 0, -425, 0, 0, 0, -425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -425, 0, -425, -425, -425, -425, 0, 0, 0, 0, 0, -425, -425, -425, -425, 0, -425, -425, -425, -425, 244, 828, 0, 0, -425, -425, -425, -425, -425, 0, 0, -425, -425, -425, -425, 0, -425, -425, -425, -425, -425, -425, -425, -425, -425, 0, 0, 0, -425, -425, 0, 0, 0, -425, -425, -425, -425, -425, -425, + 0, 0, 0, 0, 0, 0, 0, -632, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 204 - -856, 0, 0, 0, 0, 0, -856, 0, -856, 0, 0, 0, -856, 0, 0, -856, 0, 0, 0, -856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -856, 0, -856, -856, -856, -856, 0, 0, 0, 0, 0, -856, -856, -856, -856, 0, -856, -856, -856, -856, 0, 835, 248, 836, -856, -856, -856, -856, -856, 0, 0, -856, -856, -856, -856, 0, -856, -856, -856, -856, -856, -856, -856, -856, -856, 0, 0, 0, -856, -856, 0, 0, 0, -856, -856, -856, -856, -856, -856, + 0, 0, 0, 0, 0, 0, 0, -453, 0, 0, 0, 0, 0, 0, -453, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 205 - -860, 0, 0, 0, 0, 0, -860, 0, -860, 0, 0, 0, -860, 0, 0, -860, 0, 0, 0, -860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -860, 0, -860, -860, -860, -860, 0, 0, 0, 0, 0, -860, -860, -860, -860, 0, -860, -860, -860, -860, 0, 838, 839, 840, -860, -860, -860, -860, -860, 0, 0, -860, -860, -860, -860, 0, -860, -860, -860, -860, -860, -860, -860, -860, -860, 0, 0, 0, -860, -860, 0, 0, 0, -860, -860, -860, -860, -860, -860, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 206 - 0, 0, 0, 0, 0, 0, 12, 0, 249, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 207 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 505, 15, 506, 0, 50, 507, 51, 52, 0, 0, 0, 0, 53, 54, 55, 56, 57, 0, 0, 16, 58, 59, 17, 0, 508, 60, 61, 509, 62, 63, 64, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + -427, 0, 0, 0, 0, 0, -427, 0, -427, 0, 0, 0, -427, 0, 0, -427, 0, 0, 0, -427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -427, 0, -427, -427, -427, -427, 0, 0, 0, 0, 0, -427, -427, -427, -427, 0, -427, -427, -427, -427, 248, 832, 0, 0, -427, -427, -427, -427, -427, 0, 0, -427, -427, -427, -427, 0, -427, -427, -427, -427, -427, -427, -427, -427, -427, 0, 0, 0, -427, -427, 0, 0, 0, -427, -427, -427, -427, -427, -427, // State 208 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + -861, 0, 0, 0, 0, 0, -861, 0, -861, 0, 0, 0, -861, 0, 0, -861, 0, 0, 0, -861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -861, 0, -861, -861, -861, -861, 0, 0, 0, 0, 0, -861, -861, -861, -861, 0, -861, -861, -861, -861, 0, 839, 252, 840, -861, -861, -861, -861, -861, 0, 0, -861, -861, -861, -861, 0, -861, -861, -861, -861, -861, -861, -861, -861, -861, 0, 0, 0, -861, -861, 0, 0, 0, -861, -861, -861, -861, -861, -861, // State 209 - 0, -155, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -157, 0, 0, -155, 441, 0, -155, 0, -155, -155, -155, 442, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, -155, -155, 0, 0, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -865, 0, 0, 0, 0, 0, -865, 0, -865, 0, 0, 0, -865, 0, 0, -865, 0, 0, 0, -865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -865, 0, -865, -865, -865, -865, 0, 0, 0, 0, 0, -865, -865, -865, -865, 0, -865, -865, -865, -865, 0, 842, 843, 844, -865, -865, -865, -865, -865, 0, 0, -865, -865, -865, -865, 0, -865, -865, -865, -865, -865, -865, -865, -865, -865, 0, 0, 0, -865, -865, 0, 0, 0, -865, -865, -865, -865, -865, -865, // State 210 - 0, -167, 443, 0, -167, 0, 0, 0, 444, 0, 0, 0, -167, 0, -167, -167, 0, 0, 0, 0, 445, 446, 0, 0, -169, 0, 0, -167, -167, 0, -167, 0, -167, -167, -167, -167, 0, 447, 0, 0, 0, 0, 0, 0, -167, 0, -167, -167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -167, 0, -167, -167, 0, 0, 0, -167, -167, 0, 0, 0, 0, 0, 0, 0, 0, 0, -167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 253, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 211 - 0, -765, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 427, 0, -765, 428, 0, 0, 0, 0, 0, 0, 0, 0, -767, 0, 0, -765, -765, 0, -765, 0, -765, -765, -765, -765, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, -765, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, -765, -765, 0, 0, 0, -765, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 506, 16, 507, 0, 53, 508, 54, 55, 0, 0, 0, 0, 56, 57, 58, 59, 60, 0, 0, 17, 61, 62, 18, 0, 509, 63, 64, 510, 65, 66, 67, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 212 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 213 - 0, 0, 0, 0, 0, 0, 12, 851, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -155, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -157, 0, 0, -155, 441, 0, -155, 0, -155, -155, -155, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, -155, -155, 0, 0, 0, -155, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, -155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 214 - 0, 0, 0, 0, 0, 0, 12, 853, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -169, 443, 0, -169, 0, 0, 0, 444, 0, 0, 0, -169, 0, -169, -169, 0, 0, 0, 0, 445, 446, 0, 0, -171, 0, 0, -169, -169, 0, -169, 0, -169, -169, -169, -169, 0, 0, 447, 0, 0, 0, 0, 0, 0, -169, 0, -169, -169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -169, 0, -169, -169, 0, 0, 0, -169, -169, 0, 0, 0, 0, 0, 0, 0, 0, 0, -169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 215 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, -769, 0, 0, -769, 0, 0, 0, 0, 0, 0, 0, 426, 0, -769, 427, 0, 0, 0, 0, 0, 0, 0, 0, -771, 0, 0, -769, -769, 0, -769, 0, -769, -769, -769, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, 0, -769, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, 0, -769, -769, 0, 0, 0, -769, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 216 - 0, 0, 0, 0, 0, 0, 12, 856, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 217 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 854, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 218 - 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 856, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 219 - 0, 0, 0, 0, 0, 0, 12, 862, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 858, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 220 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 221 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 222 - 0, 0, 0, 0, 0, 0, 0, 0, 264, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 864, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 223 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 0, 0, 0, 0, -676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 224 - 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 225 - 0, 0, 0, 0, 0, 0, 12, -164, 69, 70, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 267, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 226 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, -680, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 227 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 228 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 229 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 230 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 231 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 232 - 0, 0, 0, 0, 0, 0, 0, 0, 196, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 233 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 234 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 235 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 236 - 0, 0, 0, 0, 0, 0, 0, -579, 276, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 200, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 882, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 237 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 238 - 0, 0, 0, 0, 0, 0, 0, -627, 0, 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 239 - 0, 0, 0, 0, 0, 0, 0, -620, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 240 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -583, 279, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 241 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 242 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -631, 0, 0, 0, 0, 0, 0, 283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 243 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -624, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 244 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 245 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 246 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 247 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 248 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 249 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 250 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 251 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 252 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 505, 15, 506, 0, 50, 507, 51, 52, 0, 0, 0, 0, 53, 54, 55, 56, 57, 0, 0, 16, 58, 59, 17, 0, 508, 60, 61, 509, 62, 63, 64, 37, 18, 0, 0, 0, 417, 908, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 253 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 254 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 255 - 0, 0, 0, 0, 0, 0, 12, 911, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 256 - 0, 0, 0, 0, 0, 0, 0, 913, 0, 0, 0, 0, 0, 0, 298, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 506, 16, 507, 0, 53, 508, 54, 55, 0, 0, 0, 0, 56, 57, 58, 59, 60, 0, 0, 17, 61, 62, 18, 0, 509, 63, 64, 510, 65, 66, 67, 38, 19, 0, 0, 0, 416, 909, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 257 - 0, 0, 0, 0, 0, 0, 0, 915, 0, 0, 0, 0, 0, 0, 299, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 258 - 0, 0, 0, 0, 0, 0, 12, 916, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 911, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 259 - 0, 0, 0, 0, 0, 0, 0, -771, 0, 0, 0, 0, 0, 0, -771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -771, 0, 0, 0, 0, 0, -771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -771, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 913, 0, 0, 0, 0, 0, 0, 301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 260 - 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 915, 0, 0, 0, 0, 0, 0, 302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 261 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 916, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 262 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 263 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302, 0, 0, 0, 0, 0, 0, 0, 0, 0, -677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -778, 0, 0, 0, 0, 0, 0, -778, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -778, 0, 0, 0, 0, 0, -778, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -778, 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -778, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 264 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, -673, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 265 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 266 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, -681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 267 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 0, 0, 0, 0, 0, 0, 0, 0, 0, -677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 268 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -653, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 269 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 270 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 271 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 272 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 273 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 274 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 275 - 0, 0, 0, 0, 0, 0, 0, -597, 0, 0, 0, 0, 0, 0, 313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 276 - 0, 0, 0, 0, 0, 0, 0, -607, 0, 0, 0, 0, 0, 0, 314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 277 - 0, 0, 0, 0, 0, 0, 0, -622, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 278 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -601, 0, 0, 0, 0, 0, 0, 314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 279 - 0, 0, 0, 0, 0, 0, 0, -619, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -611, 0, 0, 0, 0, 0, 0, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 280 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -626, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 281 - 0, 0, 0, 0, 0, 0, 0, 947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 282 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, -623, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 283 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 284 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 285 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 951, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 286 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 287 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 288 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 975, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 950, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 289 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 290 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 291 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 974, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 292 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 293 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 294 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 295 - 0, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 296 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 297 - 0, 0, 0, 0, 0, 0, 12, 990, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 298 - 0, 0, 0, 0, 0, 0, 12, 992, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 299 - 0, 0, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -772, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 300 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, -674, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 989, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 301 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 991, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 302 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 303 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, -678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 304 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 305 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 306 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 307 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 308 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 309 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 310 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 311 - 0, 0, 0, 0, 0, 0, 0, -594, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 312 - 0, 0, 0, 0, 0, 0, 0, -570, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -598, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 313 - 0, 0, 0, 0, 0, 0, 0, -580, 342, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -574, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 314 - 0, 0, 0, 0, 0, 0, 0, -621, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -584, 342, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 315 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -625, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 316 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 317 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 318 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1016, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 319 - 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 427, 0, -462, 428, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1013, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 320 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -465, 0, 0, 0, 0, 426, 0, -465, 427, 0, 0, 0, 0, 0, 0, 0, 0, -465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -465, 0, 0, 0, -465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -465, 0, -465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 321 - 0, 0, 0, 0, 0, 0, 322, 1019, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 322 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 323, 1016, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 323 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 324 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 0, 0, // State 325 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1032, 1033, 1034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1035, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 1020, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 326 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1036, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1029, 1030, 1031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1032, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 327 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1033, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 328 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 329 - 0, 0, 0, 0, 0, 0, 12, 1045, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 330 - 0, 0, 0, 0, 0, 0, 12, 1046, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 1042, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 331 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 13, 1043, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 332 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 333 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 334 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 335 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 336 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 337 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 338 - 0, 0, 0, 0, 0, 0, 0, -576, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -580, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 339 - 0, 0, 0, 0, 0, 0, 0, -567, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -571, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 340 - 0, 0, 0, 0, 0, 0, 0, -581, 366, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -585, 366, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 341 - 0, 0, 0, 0, 0, 0, 0, -598, 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -602, 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 342 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 343 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 344 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 345 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 0, 0, // State 346 - 0, 0, 0, 0, 0, 0, 322, 1073, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 1069, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 347 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 348 - 0, 0, 0, 0, 0, 0, 322, 1077, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 1073, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 349 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 350 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 351 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 352 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 353 - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 354 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 355 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 356 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 357 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 1089, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 1085, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 358 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 427, 0, 0, 428, 0, 0, 0, 0, 0, 0, 0, 0, -465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 0, -468, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 359 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 360 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 361 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -653, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -657, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 362 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 363 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 364 - 0, 0, 0, 0, 0, 0, 0, -573, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -577, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 365 - 0, 0, 0, 0, 0, 0, 0, -599, 0, 0, 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -603, 0, 0, 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 366 - 0, 0, 0, 0, 0, 0, 0, -595, 0, 0, 0, 0, 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -599, 0, 0, 0, 0, 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 367 - 0, 0, 0, 0, 0, 0, 0, -571, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -575, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 368 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 369 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 370 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1032, 1033, 1034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1121, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1029, 1030, 1031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1117, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 371 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 372 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 373 - 688, 0, 0, 0, 0, 0, 12, 0, 13, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, 415, 416, 14, 0, 0, 0, 0, 0, 49, 0, 15, 506, 0, 0, 507, 0, 52, 0, 0, 0, 0, 0, 54, 55, 0, 57, 0, 0, 16, 0, 59, 17, 0, 508, 60, 61, 0, 62, 0, 0, 37, 18, 0, 0, 0, 417, 0, 0, 0, 0, 418, 419, 420, 510, 421, 422, + 693, 0, 0, 0, 0, 0, 13, 0, 14, 0, 0, 0, 410, 0, 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 413, 414, 415, 15, 0, 0, 0, 0, 0, 52, 0, 16, 507, 0, 0, 508, 0, 55, 0, 0, 0, 0, 0, 57, 58, 0, 60, 0, 0, 17, 0, 62, 18, 0, 509, 63, 64, 0, 65, 0, 0, 38, 19, 0, 0, 0, 416, 0, 0, 0, 0, 417, 418, 419, 511, 420, 421, // State 374 - 0, 0, 0, 0, 0, 0, 0, -596, 0, 0, 0, 0, 0, 0, 386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -600, 0, 0, 0, 0, 0, 0, 386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 375 - 0, 0, 0, 0, 0, 0, 0, -572, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -576, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 376 - 0, 0, 0, 0, 0, 0, 0, -577, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -581, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 377 - 0, 0, 0, 0, 0, 0, 0, -568, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -572, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 378 - 0, 0, 0, 0, 0, 0, 322, 0, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 379 - 0, 0, 0, 0, 0, 0, 0, 1137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 1133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 380 - 0, 0, 0, 0, 0, 0, 322, 1140, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 1136, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 381 - 0, 0, 0, 0, 0, 0, 0, 1141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 1137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 382 - 0, 0, 0, 0, 0, 0, 322, 1143, 323, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, 973, 974, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, 0, 418, 419, 420, 0, 421, 422, + 0, 0, 0, 0, 0, 0, 323, 1139, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971, 972, 973, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 0, 417, 418, 419, 0, 420, 421, // State 383 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 384 - 0, 0, 0, 0, 0, 0, 0, -578, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -582, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 385 - 0, 0, 0, 0, 0, 0, 0, -569, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -573, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 386 - 0, 0, 0, 0, 0, 0, 0, -574, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -578, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 387 - 0, 0, 0, 0, 0, 0, 0, -575, 0, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, -579, 0, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 388 - 0, 0, 0, 0, 0, 0, 0, 1161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 1157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 389 - 0, 0, 0, 0, 0, 0, 0, 1162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 1158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 420, 0, // State 390 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 391 - -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, 0, -182, 0, -182, -182, -182, -182, -182, 0, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, -182, 0, 0, 0, -182, -182, -182, -182, -182, -182, 0, -182, 0, 0, 0, 0, 0, 0, 0, 0, -182, 0, 0, -182, -182, 0, -182, 0, -182, -182, 0, 0, 0, -182, -182, 0, 0, 0, 0, 0, 0, 0, 0, 0, -182, -182, -182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, 0, -184, 0, -184, -184, -184, -184, -184, 0, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, 0, 0, 0, -184, -184, -184, -184, -184, -184, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, -184, -184, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 424, // State 392 - -911, -911, 0, -911, 20, -911, 0, -911, 0, 0, -911, -911, 0, -911, -911, 0, -911, 0, 0, 0, 0, 0, -911, -911, -911, 0, -911, -911, 0, -911, -911, -911, -911, -911, -911, 0, -911, 0, -911, 0, 0, 0, 0, -911, -911, -911, -911, -911, 0, -911, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, 0, -911, -911, 0, -911, 0, -911, -911, 0, 0, 0, -911, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, -911, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -916, -916, 0, -916, 21, -916, 0, -916, 0, 0, -916, -916, 0, -916, -916, 0, -916, 0, 0, 0, 0, 0, -916, -916, -916, 0, -916, -916, 0, -916, -916, -916, -916, -916, -916, 0, -916, -916, 0, -916, 0, 0, 0, 0, -916, -916, -916, -916, -916, 0, -916, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, 0, -916, -916, 0, -916, 0, -916, -916, 0, 0, 0, -916, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, -916, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 393 - -542, 0, 0, -542, 0, -542, 0, -542, 0, 0, -542, -542, 0, -542, -542, 0, -542, 0, 0, 0, 0, 0, -542, -542, -542, 0, -542, 0, 0, -542, 0, -542, 0, 0, 0, 0, -542, 0, -542, 0, 0, 0, 0, -542, 0, -542, 0, -542, 0, -542, 0, 0, 0, 0, 0, 0, 0, 0, -542, 0, 0, -542, -542, 0, -542, 0, 0, 0, 0, 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -542, -542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -546, 0, 0, -546, 0, -546, 0, -546, 0, 0, -546, -546, 0, -546, -546, 0, -546, 0, 0, 0, 0, 0, -546, -546, -546, 0, -546, 0, 0, -546, 0, -546, 0, 0, 0, 0, -546, 0, 0, -546, 0, 0, 0, 0, -546, 0, -546, 0, -546, 0, -546, 0, 0, 0, 0, 0, 0, 0, 0, -546, 0, 0, -546, -546, 0, -546, 0, 0, 0, 0, 0, 0, 0, 425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -546, -546, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 394 - -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, 0, -238, 0, -238, -238, -238, -238, -238, 0, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, -238, 0, 0, 0, -238, -238, -238, -238, -238, -238, 0, -238, 0, 0, 0, 0, 0, 0, 0, 0, -238, 0, 0, -238, -238, 0, -238, 0, -238, -238, 0, 0, 0, -238, -238, 0, 0, 0, 0, 0, 0, 0, 0, 0, -238, -238, -238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, 0, -240, 0, -240, -240, -240, -240, -240, 0, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, 0, 0, 0, -240, -240, -240, -240, -240, -240, 0, -240, 0, 0, 0, 0, 0, 0, 0, 0, -240, 0, 0, -240, -240, 0, -240, 0, -240, -240, 0, 0, 0, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 395 - -247, -247, -247, -247, -247, -247, 22, -247, -247, -247, -247, -247, -247, -247, -247, -247, -247, 0, 23, 0, -247, -247, -247, -247, -247, 0, -247, -247, -247, -247, -247, -247, -247, -247, -247, -247, -247, -247, -247, 0, 0, 0, 24, -247, -247, -247, -247, -247, 0, -247, 0, 0, 0, 0, 0, 0, 0, 0, -247, 0, 0, -247, -247, 0, -247, 0, -247, -247, 0, 0, 0, -247, -247, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, -247, -247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -745, -745, -745, -745, -745, -745, 0, -745, -745, 26, -745, -745, -745, -745, -745, -745, -745, 0, 0, 0, -745, -745, -745, -745, -745, 0, -745, -745, -745, -745, -745, -745, -745, -745, -745, -745, -745, -745, -745, -745, 0, 0, 0, 0, -745, -745, -745, -745, -745, 0, -745, 0, 0, 0, 0, 0, 0, 0, 0, -745, 0, 0, -745, -745, 0, -745, 0, -745, -745, 0, 0, 0, -745, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, -745, -745, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 396 - -741, -741, -741, -741, -741, -741, 0, -741, -741, 25, -741, -741, -741, -741, -741, -741, -741, 0, 0, 0, -741, -741, -741, -741, -741, 0, -741, -741, -741, -741, -741, -741, -741, -741, -741, -741, -741, -741, -741, 0, 0, 0, 0, -741, -741, -741, -741, -741, 0, -741, 0, 0, 0, 0, 0, 0, 0, 0, -741, 0, 0, -741, -741, 0, -741, 0, -741, -741, 0, 0, 0, -741, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, -741, -741, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -508, 0, 0, -508, 0, -508, 0, -508, 0, 0, -508, -508, 0, -508, -508, 0, -508, 0, 0, 0, 0, 0, -508, -508, -508, 0, -508, 0, 0, -508, 0, -508, 0, 0, 0, 0, -508, 0, 0, -508, 0, 0, 0, 0, -508, 0, -508, -508, -508, 0, -508, 0, 0, 0, 0, 0, 0, 0, 0, -508, 0, 0, -508, -508, 0, -508, 0, 0, 0, 0, 0, 0, 0, -508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -508, -508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 397 - -504, 0, 0, -504, 0, -504, 0, -504, 0, 0, -504, -504, 0, -504, -504, 0, -504, 0, 0, 0, 0, 0, -504, -504, -504, 0, -504, 0, 0, -504, 0, -504, 0, 0, 0, 0, -504, 0, -504, 0, 0, 0, 0, -504, 0, -504, -504, -504, 0, -504, 0, 0, 0, 0, 0, 0, 0, 0, -504, 0, 0, -504, -504, 0, -504, 0, 0, 0, 0, 0, 0, 0, -504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504, -504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, 0, -185, 0, -185, -185, -185, -185, -185, 0, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, 0, 0, 0, -185, -185, -185, -185, -185, -185, 0, -185, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, 0, -185, -185, 0, -185, 0, -185, -185, 0, 0, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 398 - -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, 0, -183, 0, -183, -183, -183, -183, -183, 0, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, 0, 0, 0, -183, -183, -183, -183, -183, -183, 0, -183, 0, 0, 0, 0, 0, 0, 0, 0, -183, 0, 0, -183, -183, 0, -183, 0, -183, -183, 0, 0, 0, -183, -183, 0, 0, 0, 0, 0, 0, 0, 0, 0, -183, -183, -183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -834, -834, -834, -834, -834, -834, 0, -834, -834, 0, -834, -834, -834, -834, -834, -834, -834, 0, 0, 0, -834, -834, -834, -834, -834, 0, -834, -834, -834, -834, -834, -834, -834, -834, -834, -834, -834, -834, -834, -834, 0, 0, 0, 0, -834, -834, -834, -834, -834, 0, -834, 0, 0, 0, 0, 0, 0, 0, 0, -834, 0, 0, -834, -834, 0, -834, 0, -834, -834, 0, 0, 0, -834, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, -834, -834, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 399 - -829, -829, -829, -829, -829, -829, 0, -829, -829, 0, -829, -829, -829, -829, -829, -829, -829, 0, 0, 0, -829, -829, -829, -829, -829, 0, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, 0, 0, 0, 0, -829, -829, -829, -829, -829, 0, -829, 0, 0, 0, 0, 0, 0, 0, 0, -829, 0, 0, -829, -829, 0, -829, 0, -829, -829, 0, 0, 0, -829, -829, 0, 0, 0, 0, 0, 0, 0, 0, 0, -829, -829, -829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, 0, -186, 0, -186, -186, -186, -186, -186, 0, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, 0, 0, 0, -186, -186, -186, -186, -186, -186, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, -186, -186, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 400 - -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, 0, -184, 0, -184, -184, -184, -184, -184, 0, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, -184, 0, 0, 0, -184, -184, -184, -184, -184, -184, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, -184, -184, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -839, 0, 0, -839, 0, -839, 0, -839, 0, 0, -839, -839, 0, -839, -839, 0, -839, 0, 0, 0, 0, 0, -839, -839, -839, 0, -839, 0, 0, -839, 0, -839, 0, 0, 0, 0, -839, 0, 0, -839, 0, 0, 0, 0, -839, 0, -839, 0, -839, 0, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -839, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -839, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 401 - -834, 0, 0, -834, 0, -834, 0, -834, 0, 0, -834, -834, 0, -834, -834, 0, -834, 0, 0, 0, 0, 0, -834, -834, -834, 0, -834, 0, 0, -834, 0, -834, 0, 0, 0, 0, -834, 0, -834, 0, 0, 0, 0, -834, 0, -834, 0, -834, 0, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -834, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -834, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -160, 0, 0, -160, 0, -160, 0, -160, 0, 0, -160, -160, 0, -160, -160, 0, -160, 0, 0, 0, 0, 0, -160, -160, -160, 0, -160, 0, 0, -160, 0, -160, 0, 0, 0, 0, -160, 0, 0, -160, 0, 0, 0, 0, -160, 0, -160, 440, -160, 0, -160, 0, 0, 0, 0, 0, 0, 0, 0, -160, 0, 0, -160, -160, 0, -160, 0, 0, 0, 0, 0, 0, 0, -160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -160, -160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 402 - -160, 0, 0, -160, 0, -160, 0, -160, 0, 0, -160, -160, 0, -160, -160, 0, -160, 0, 0, 0, 0, 0, -160, -160, -160, 0, -160, 0, 0, -160, 0, -160, 0, 0, 0, 0, -160, 0, -160, 0, 0, 0, 0, -160, 0, -160, 440, -160, 0, -160, 0, 0, 0, 0, 0, 0, 0, 0, -160, 0, 0, -160, -160, 0, -160, 0, 0, 0, 0, 0, 0, 0, -160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -160, -160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -422, 0, 0, -422, 0, -422, 0, -422, 0, 0, -422, -422, 0, -422, 30, 0, -422, 0, 0, 0, 0, 0, -422, -422, -422, 0, -422, 0, 0, -422, 0, -422, 0, 0, 0, 0, -422, 0, 0, -422, 0, 0, 0, 0, 0, 0, -422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 403 - -420, 0, 0, -420, 0, -420, 0, -420, 0, 0, -420, -420, 0, -420, 29, 0, -420, 0, 0, 0, 0, 0, -420, -420, -420, 0, -420, 0, 0, -420, 0, -420, 0, 0, 0, 0, -420, 0, -420, 0, 0, 0, 0, 0, 0, -420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -838, 0, 0, -838, 0, -838, 0, -838, 0, 0, -838, -838, 0, -838, -838, 0, -838, 0, 0, 0, 0, 0, -838, -838, -838, 0, -838, 0, 0, -838, 0, -838, 0, 0, 0, 0, -838, 0, 0, -838, 0, 0, 0, 0, -838, 0, -838, 0, -838, 0, -838, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -838, -838, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -838, -838, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 404 - -833, 0, 0, -833, 0, -833, 0, -833, 0, 0, -833, -833, 0, -833, -833, 0, -833, 0, 0, 0, 0, 0, -833, -833, -833, 0, -833, 0, 0, -833, 0, -833, 0, 0, 0, 0, -833, 0, -833, 0, 0, 0, 0, -833, 0, -833, 0, -833, 0, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, -833, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -383, -383, -383, -383, -383, -383, 0, -383, -383, 0, -383, -383, -383, -383, -383, -383, -383, 0, 0, 0, -383, -383, -383, -383, -383, 0, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, 0, 0, 0, 0, -383, -383, -383, -383, -383, 0, -383, 0, 0, 0, 0, 0, 0, 0, 0, -383, 0, 0, -383, -383, 0, -383, 0, -383, -383, 0, 0, 0, -383, -383, 0, 0, 0, 0, 0, 0, 0, 0, 0, -383, -383, -383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 405 - -381, -381, -381, -381, -381, -381, 0, -381, -381, 0, -381, -381, -381, -381, -381, -381, -381, 0, 0, 0, -381, -381, -381, -381, -381, 0, -381, -381, -381, -381, -381, -381, -381, -381, -381, -381, -381, -381, -381, 0, 0, 0, 0, -381, -381, -381, -381, -381, 0, -381, 0, 0, 0, 0, 0, 0, 0, 0, -381, 0, 0, -381, -381, 0, -381, 0, -381, -381, 0, 0, 0, -381, -381, 0, 0, 0, 0, 0, 0, 0, 0, 0, -381, -381, -381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -851, 0, 0, -851, 0, -851, 0, -851, 0, 0, -851, -851, 0, -851, -851, 0, -851, 0, 0, 0, 0, 0, -851, -851, -851, 0, -851, 0, 0, -851, 0, -851, 0, 0, 0, 0, -851, 0, 0, -851, 0, 0, 0, 0, 0, 0, -851, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -851, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 406 - -846, 0, 0, -846, 0, -846, 0, -846, 0, 0, -846, -846, 0, -846, -846, 0, -846, 0, 0, 0, 0, 0, -846, -846, -846, 0, -846, 0, 0, -846, 0, -846, 0, 0, 0, 0, -846, 0, -846, 0, 0, 0, 0, 0, 0, -846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -850, 0, 0, -850, 0, -850, 0, -850, 0, 0, -850, -850, 0, -850, -850, 0, -850, 0, 0, 0, 0, 0, -850, -850, -850, 0, -850, 0, 0, -850, 0, -850, 0, 0, 0, 0, -850, 0, 0, -850, 0, 0, 0, 0, 0, 0, -850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 407 - -845, 0, 0, -845, 0, -845, 0, -845, 0, 0, -845, -845, 0, -845, -845, 0, -845, 0, 0, 0, 0, 0, -845, -845, -845, 0, -845, 0, 0, -845, 0, -845, 0, 0, 0, 0, -845, 0, -845, 0, 0, 0, 0, 0, 0, -845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -537, 0, 0, -537, 0, -537, 0, -537, 0, 0, -537, -537, 0, -537, -537, 0, -537, 0, 0, 0, 0, 0, -537, -537, -537, 0, -537, 0, 0, -537, 0, -537, 0, 0, 0, 0, -537, 0, 0, -537, 0, 0, 0, 0, 0, 0, -537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 408 - -533, 0, 0, -533, 0, -533, 0, -533, 0, 0, -533, -533, 0, -533, -533, 0, -533, 0, 0, 0, 0, 0, -533, -533, -533, 0, -533, 0, 0, -533, 0, -533, 0, 0, 0, 0, -533, 0, -533, 0, 0, 0, 0, 0, 0, -533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -368, -368, 0, -368, 0, -368, 0, -368, 0, 0, -368, -368, 0, -368, -368, 0, -368, 0, 0, 0, 0, 0, -368, -368, -368, 0, -368, -368, 0, -368, -368, -368, -368, -368, -368, 0, -368, -368, 0, -368, 0, 0, 0, 0, -368, 34, -368, -368, -368, 0, -368, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, 0, -368, -368, 0, -368, 0, -368, -368, 0, 0, 0, -368, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, -368, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 409 - -366, -366, 0, -366, 0, -366, 0, -366, 0, 0, -366, -366, 0, -366, -366, 0, -366, 0, 0, 0, 0, 0, -366, -366, -366, 0, -366, -366, 0, -366, -366, -366, -366, -366, -366, 0, -366, 0, -366, 0, 0, 0, 0, -366, 33, -366, -366, -366, 0, -366, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, 0, -366, -366, 0, -366, 0, -366, -366, 0, 0, 0, -366, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, -366, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -888, 0, 0, 0, 0, 0, -888, 0, 0, -888, 0, 0, 0, -888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -888, -888, -888, -888, 0, 0, 0, 0, 0, 0, 0, -888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -888, 0, 0, 0, -888, 0, 0, 0, 0, -888, -888, -888, 0, -888, -888, // State 410 - 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, 0, 0, -883, 0, 0, -883, 0, 0, 0, -883, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -883, -883, -883, -883, 0, 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, -883, 0, 0, 0, 0, -883, -883, -883, 0, -883, -883, + 0, 0, 0, 0, 0, 0, -889, 0, 0, 0, 0, 0, -889, 0, 0, -889, 0, 0, 0, -889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -889, -889, -889, -889, 0, 0, 0, 0, 0, 0, 0, -889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -889, 0, 0, 0, -889, 0, 0, 0, 0, -889, -889, -889, 0, -889, -889, // State 411 - 0, 0, 0, 0, 0, 0, -884, 0, 0, 0, 0, 0, -884, 0, 0, -884, 0, 0, 0, -884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -884, -884, -884, -884, 0, 0, 0, 0, 0, 0, 0, -884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -884, 0, 0, 0, -884, 0, 0, 0, 0, -884, -884, -884, 0, -884, -884, + -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, 0, -212, 0, -212, -212, -212, -212, -212, 0, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, 0, 0, 0, -212, -212, -212, -212, -212, -212, 0, -212, 0, 0, 0, 0, 0, 0, 0, 0, -212, 0, 0, -212, -212, 0, -212, 0, -212, -212, 0, 0, 0, -212, -212, 0, 0, 0, 0, 0, 0, 0, 0, 0, -212, -212, -212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 412 - -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, 0, -210, 0, -210, -210, -210, -210, -210, 0, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, 0, 0, 0, -210, -210, -210, -210, -210, -210, 0, -210, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, 0, -210, -210, 0, -210, 0, -210, -210, 0, 0, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, 0, -210, 0, -210, -210, -210, -210, -210, 0, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, -210, 0, 0, 0, -210, -210, -210, -210, -210, -210, 0, -210, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, 0, -210, -210, 0, -210, 0, -210, -210, 0, 0, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 413 - -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, 0, -208, 0, -208, -208, -208, -208, -208, 0, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, 0, 0, 0, -208, -208, -208, -208, -208, -208, 0, -208, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, 0, -208, -208, 0, -208, 0, -208, -208, 0, 0, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, 0, -211, 0, -211, -211, -211, -211, -211, 0, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, 0, 0, 0, -211, -211, -211, -211, -211, -211, 0, -211, 0, 0, 0, 0, 0, 0, 0, 0, -211, 0, 0, -211, -211, 0, -211, 0, -211, -211, 0, 0, 0, -211, -211, 0, 0, 0, 0, 0, 0, 0, 0, 0, -211, -211, -211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 414 - -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, 0, -209, 0, -209, -209, -209, -209, -209, 0, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, 0, 0, 0, -209, -209, -209, -209, -209, -209, 0, -209, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, 0, -209, -209, 0, -209, 0, -209, -209, 0, 0, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, 0, -209, 0, -209, -209, -209, -209, -209, 0, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, 0, 0, 0, -209, -209, -209, -209, -209, -209, 0, -209, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, 0, -209, -209, 0, -209, 0, -209, -209, 0, 0, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 415 - -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, 0, -207, 0, -207, -207, -207, -207, -207, 0, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, 0, 0, 0, -207, -207, -207, -207, -207, -207, 0, -207, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, 0, -207, -207, 0, -207, 0, -207, -207, 0, 0, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, -890, 0, 0, -890, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -890, -890, -890, -890, 0, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, -890, 0, 0, 0, 0, -890, -890, -890, 0, -890, -890, // State 416 - 0, 0, 0, 0, 0, 0, -885, 0, 0, 0, 0, 0, -885, 0, 0, -885, 0, 0, 0, -885, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -885, -885, -885, -885, 0, 0, 0, 0, 0, 0, 0, -885, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -885, 0, 0, 0, -885, 0, 0, 0, 0, -885, -885, -885, 0, -885, -885, + -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, 0, -335, 0, -335, -335, -335, -335, -335, 0, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, -335, 0, 0, 0, -335, -335, -335, -335, -335, -335, 0, -335, 0, 0, 0, 0, 0, 0, 0, 0, -335, 0, 0, -335, -335, 0, -335, 0, -335, -335, 0, 0, 0, -335, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, -335, -335, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 417 - -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, 0, -333, 0, -333, -333, -333, -333, -333, 0, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, 0, 0, 0, -333, -333, -333, -333, -333, -333, 0, -333, 0, 0, 0, 0, 0, 0, 0, 0, -333, 0, 0, -333, -333, 0, -333, 0, -333, -333, 0, 0, 0, -333, -333, 0, 0, 0, 0, 0, 0, 0, 0, 0, -333, -333, -333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, 0, -334, 0, -334, -334, -334, -334, -334, 0, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, -334, 0, 0, 0, -334, -334, -334, -334, -334, -334, 0, -334, 0, 0, 0, 0, 0, 0, 0, 0, -334, 0, 0, -334, -334, 0, -334, 0, -334, -334, 0, 0, 0, -334, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, -334, -334, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 418 - -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, 0, -332, 0, -332, -332, -332, -332, -332, 0, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, -332, 0, 0, 0, -332, -332, -332, -332, -332, -332, 0, -332, 0, 0, 0, 0, 0, 0, 0, 0, -332, 0, 0, -332, -332, 0, -332, 0, -332, -332, 0, 0, 0, -332, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, -332, -332, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, 0, -333, 0, -333, -333, -333, -333, -333, 0, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, -333, 0, 0, 0, -333, -333, -333, -333, -333, -333, 0, -333, 0, 0, 0, 0, 0, 0, 0, 0, -333, 0, 0, -333, -333, 0, -333, 0, -333, -333, 0, 0, 0, -333, -333, 0, 0, 0, 0, 0, 0, 0, 0, 0, -333, -333, -333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 419 - -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, 0, -331, 0, -331, -331, -331, -331, -331, 0, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, -331, 0, 0, 0, -331, -331, -331, -331, -331, -331, 0, -331, 0, 0, 0, 0, 0, 0, 0, 0, -331, 0, 0, -331, -331, 0, -331, 0, -331, -331, 0, 0, 0, -331, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, -331, -331, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, 0, -425, 0, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, -425, 0, 0, 0, -425, -425, -425, -425, -425, -425, 0, -425, 0, 0, 0, 0, 0, 0, 0, 0, -425, 0, 0, -425, -425, 0, -425, -425, -425, -425, 0, 0, 0, -425, -425, 0, 0, 0, 0, 0, 0, 0, 0, 0, -425, -425, -425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 420 - -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, 0, -423, 0, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, -423, 0, 0, 0, -423, -423, -423, -423, -423, -423, 0, -423, 0, 0, 0, 0, 0, 0, 0, 0, -423, 0, 0, -423, -423, 0, -423, -423, -423, -423, 0, 0, 0, -423, -423, 0, 0, 0, 0, 0, 0, 0, 0, 0, -423, -423, -423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, 0, -139, 0, -139, -139, -139, -139, -139, 0, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, 0, 0, 0, -139, -139, -139, -139, -139, -139, 0, -139, 0, 0, 0, 0, 0, 0, 0, 0, -139, 0, 0, -139, -139, 0, -139, 0, -139, -139, 0, 0, 0, -139, -139, 0, 0, 0, 0, 0, 0, 0, 0, 0, -139, -139, -139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -139, // State 421 - -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, 0, -139, 0, -139, -139, -139, -139, -139, 0, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, 0, 0, 0, -139, -139, -139, -139, -139, -139, 0, -139, 0, 0, 0, 0, 0, 0, 0, 0, -139, 0, 0, -139, -139, 0, -139, 0, -139, -139, 0, 0, 0, -139, -139, 0, 0, 0, 0, 0, 0, 0, 0, 0, -139, -139, -139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -139, + -545, 0, 0, -545, 0, -545, 0, -545, 0, 0, -545, -545, 0, -545, -545, 0, -545, 0, 0, 0, 0, 0, -545, -545, -545, 0, -545, 0, 0, -545, 0, -545, 0, 0, 0, 0, -545, 0, 0, -545, 0, 0, 0, 0, -545, 0, -545, 0, -545, 0, -545, 0, 0, 0, 0, 0, 0, 0, 0, -545, 0, 0, -545, -545, 0, -545, 0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -545, -545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 422 - -541, 0, 0, -541, 0, -541, 0, -541, 0, 0, -541, -541, 0, -541, -541, 0, -541, 0, 0, 0, 0, 0, -541, -541, -541, 0, -541, 0, 0, -541, 0, -541, 0, 0, 0, 0, -541, 0, -541, 0, 0, 0, 0, -541, 0, -541, 0, -541, 0, -541, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, -541, -541, 0, -541, 0, 0, 0, 0, 0, 0, 0, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, -541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -159, 0, 0, -159, 0, -159, 0, -159, 0, 0, -159, -159, 0, -159, -159, 0, -159, 0, 0, 0, 0, 0, -159, -159, -159, 0, -159, 0, 0, -159, 0, -159, 0, 0, 0, 0, -159, 0, 0, -159, 0, 0, 0, 0, -159, 0, -159, 513, -159, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, -159, -159, 0, -159, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 423 - -159, 0, 0, -159, 0, -159, 0, -159, 0, 0, -159, -159, 0, -159, -159, 0, -159, 0, 0, 0, 0, 0, -159, -159, -159, 0, -159, 0, 0, -159, 0, -159, 0, 0, 0, 0, -159, 0, -159, 0, 0, 0, 0, -159, 0, -159, 512, -159, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, -159, -159, 0, -159, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, 0, -140, 0, -140, -140, -140, -140, -140, 0, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, 0, 0, 0, -140, -140, -140, -140, -140, -140, 0, -140, 0, 0, 0, 0, 0, 0, 0, 0, -140, 0, 0, -140, -140, 0, -140, 0, -140, -140, 0, 0, 0, -140, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, -140, -140, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -140, // State 424 - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, 0, -140, 0, -140, -140, -140, -140, -140, 0, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, 0, 0, 0, -140, -140, -140, -140, -140, -140, 0, -140, 0, 0, 0, 0, 0, 0, 0, 0, -140, 0, 0, -140, -140, 0, -140, 0, -140, -140, 0, 0, 0, -140, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, -140, -140, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -140, + 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, -111, 0, 0, -111, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, -111, -111, -111, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, -111, 0, 0, 0, 0, -111, -111, -111, 0, -111, -111, // State 425 - 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, -111, 0, 0, -111, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, -111, -111, -111, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, 0, 0, 0, 0, 0, 0, -111, 0, 0, 0, -111, 0, 0, 0, 0, -111, -111, -111, 0, -111, -111, + 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, 0, 0, -152, 0, 0, -152, 0, 0, 0, -152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152, -152, -152, -152, 0, 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, -152, 0, 0, 0, 0, -152, -152, -152, 0, -152, -152, // State 426 - 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, 0, 0, -152, 0, 0, -152, 0, 0, 0, -152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152, -152, -152, -152, 0, 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152, 0, 0, 0, -152, 0, 0, 0, 0, -152, -152, -152, 0, -152, -152, + 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, 0, 0, -153, 0, 0, -153, 0, 0, 0, -153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153, -153, -153, -153, 0, 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, -153, 0, 0, 0, 0, -153, -153, -153, 0, -153, -153, // State 427 - 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, 0, 0, -153, 0, 0, -153, 0, 0, 0, -153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153, -153, -153, -153, 0, 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153, 0, 0, 0, -153, 0, 0, 0, 0, -153, -153, -153, 0, -153, -153, + -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, 0, -241, 0, -241, -241, -241, -241, -241, 0, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, 0, 0, 0, -241, -241, -241, -241, -241, -241, 0, -241, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, 0, -241, -241, 0, -241, 0, -241, -241, 0, 0, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 428 - 0, 0, 0, 0, 0, 0, -305, 0, 0, 0, 0, 0, -305, 0, 0, -305, 0, 0, 0, -305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -305, -305, -305, -305, 0, 0, 0, 0, 0, 0, 0, -305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -305, 0, 0, 0, -305, 0, 0, 0, 0, -305, -305, -305, 0, -305, -305, + 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, 0, 0, -307, 0, 0, -307, 0, 0, 0, -307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -307, -307, -307, -307, 0, 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, -307, 0, 0, 0, 0, -307, -307, -307, 0, -307, -307, // State 429 - 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, 0, 0, -306, 0, 0, -306, 0, 0, 0, -306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -306, -306, -306, -306, 0, 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, -306, 0, 0, 0, 0, -306, -306, -306, 0, -306, -306, + 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, 0, 0, -308, 0, 0, -308, 0, 0, 0, -308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -308, -308, -308, -308, 0, 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, -308, 0, 0, 0, 0, -308, -308, -308, 0, -308, -308, // State 430 - 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, 0, 0, -307, 0, 0, -307, 0, 0, 0, -307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -307, -307, -307, -307, 0, 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -307, 0, 0, 0, -307, 0, 0, 0, 0, -307, -307, -307, 0, -307, -307, + 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, 0, 0, -309, 0, 0, -309, 0, 0, 0, -309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -309, -309, -309, -309, 0, 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, -309, 0, 0, 0, 0, -309, -309, -309, 0, -309, -309, // State 431 - 0, 0, 0, 0, 0, 0, -304, 0, 0, 0, 0, 0, -304, 0, 0, -304, 0, 0, 0, -304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -304, -304, -304, -304, 0, 0, 0, 0, 0, 0, 0, -304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -304, 0, 0, 0, -304, 0, 0, 0, 0, -304, -304, -304, 0, -304, -304, + 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, 0, 0, -306, 0, 0, -306, 0, 0, 0, -306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -306, -306, -306, -306, 0, 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -306, 0, 0, 0, -306, 0, 0, 0, 0, -306, -306, -306, 0, -306, -306, // State 432 - 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, 0, 0, -308, 0, 0, -308, 0, 0, 0, -308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -308, -308, -308, -308, 0, 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -308, 0, 0, 0, -308, 0, 0, 0, 0, -308, -308, -308, 0, -308, -308, + 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, -310, 0, 0, -310, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, -310, 0, 0, 0, 0, -310, -310, -310, 0, -310, -310, // State 433 - 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, 0, 0, -309, 0, 0, -309, 0, 0, 0, -309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -309, -309, -309, -309, 0, 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -309, 0, 0, 0, -309, 0, 0, 0, 0, -309, -309, -309, 0, -309, -309, + 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, 0, 0, -311, 0, 0, -311, 0, 0, 0, -311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -311, -311, -311, -311, 0, 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, -311, 0, 0, 0, 0, -311, -311, -311, 0, -311, -311, // State 434 - 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, -310, 0, 0, -310, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, -310, -310, -310, 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -310, 0, 0, 0, -310, 0, 0, 0, 0, -310, -310, -310, 0, -310, -310, + 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, 0, 0, -312, 0, 0, -312, 0, 0, 0, -312, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -312, -312, -312, -312, 0, 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, -312, 0, 0, 0, 0, -312, -312, -312, 0, -312, -312, // State 435 - 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, 0, 0, -312, 0, 0, -312, 0, 0, 0, -312, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -312, -312, -312, -312, 0, 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 0, 0, 0, 0, 0, -312, 0, 0, 0, -312, 0, 0, 0, 0, -312, -312, -312, 0, -312, -312, + 0, 0, 0, 0, 0, 0, -314, 0, 0, 0, 0, 0, -314, 0, 0, -314, 0, 0, 0, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, -314, -314, -314, 0, 0, 0, 0, 0, 0, 0, -314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, -314, 0, 0, 0, -314, 0, 0, 0, 0, -314, -314, -314, 0, -314, -314, // State 436 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 437 - 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 438 - -88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 439 - 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, -119, 0, 0, -119, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, -119, -119, -119, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, -119, 0, 0, 0, 0, -119, -119, -119, 0, -119, -119, + 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, -119, 0, 0, -119, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, -119, -119, -119, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, -119, 0, 0, 0, 0, -119, -119, -119, 0, -119, -119, // State 440 - 0, 0, 0, 0, 0, 0, -769, 0, 0, 0, 0, 0, -769, 0, 0, -769, 0, 0, 0, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, -769, -769, -769, 0, 0, 0, 0, 0, 0, 0, -769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -769, 0, 0, 0, -769, 0, 0, 0, 0, -769, -769, -769, 0, -769, -769, + 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, -773, 0, 0, -773, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -773, -773, -773, -773, 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -773, 0, 0, 0, -773, 0, 0, 0, 0, -773, -773, -773, 0, -773, -773, // State 441 - 0, 0, 0, 0, 0, 0, -770, 0, 0, 0, 0, 0, -770, 0, 0, -770, 0, 0, 0, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, -770, -770, -770, 0, 0, 0, 0, 0, 0, 0, -770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -770, 0, 0, 0, -770, 0, 0, 0, 0, -770, -770, -770, 0, -770, -770, + 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, -774, 0, 0, -774, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -774, -774, -774, -774, 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -774, 0, 0, 0, -774, 0, 0, 0, 0, -774, -774, -774, 0, -774, -774, // State 442 - 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, 0, 0, -495, 0, 0, -495, 0, 0, 0, -495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -495, -495, -495, -495, 0, 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, -495, 0, 0, 0, 0, -495, -495, -495, 0, -495, -495, + 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, -498, 0, 0, -498, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, -498, -498, -498, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, -498, 0, 0, 0, 0, -498, -498, -498, 0, -498, -498, // State 443 - 0, 0, 0, 0, 0, 0, -492, 0, 0, 0, 0, 0, -492, 0, 0, -492, 0, 0, 0, -492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -492, -492, -492, -492, 0, 0, 0, 0, 0, 0, 0, -492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -492, 0, 0, 0, -492, 0, 0, 0, 0, -492, -492, -492, 0, -492, -492, + 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, 0, 0, -495, 0, 0, -495, 0, 0, 0, -495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -495, -495, -495, -495, 0, 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -495, 0, 0, 0, -495, 0, 0, 0, 0, -495, -495, -495, 0, -495, -495, // State 444 - 0, 0, 0, 0, 0, 0, -493, 0, 0, 0, 0, 0, -493, 0, 0, -493, 0, 0, 0, -493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -493, -493, -493, -493, 0, 0, 0, 0, 0, 0, 0, -493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -493, 0, 0, 0, -493, 0, 0, 0, 0, -493, -493, -493, 0, -493, -493, + 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, 0, 0, -496, 0, 0, -496, 0, 0, 0, -496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -496, -496, -496, -496, 0, 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, -496, 0, 0, 0, 0, -496, -496, -496, 0, -496, -496, // State 445 - 0, 0, 0, 0, 0, 0, -494, 0, 0, 0, 0, 0, -494, 0, 0, -494, 0, 0, 0, -494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -494, -494, -494, -494, 0, 0, 0, 0, 0, 0, 0, -494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -494, 0, 0, 0, -494, 0, 0, 0, 0, -494, -494, -494, 0, -494, -494, + 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, -497, 0, 0, -497, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, -497, -497, -497, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, -497, 0, 0, 0, 0, -497, -497, -497, 0, -497, -497, // State 446 - 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, 0, 0, -496, 0, 0, -496, 0, 0, 0, -496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -496, -496, -496, -496, 0, 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -496, 0, 0, 0, -496, 0, 0, 0, 0, -496, -496, -496, 0, -496, -496, + 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, -499, 0, 0, -499, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, -499, -499, -499, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, -499, 0, 0, 0, 0, -499, -499, -499, 0, -499, -499, // State 447 - -380, -380, -380, -380, -380, -380, 0, -380, -380, 0, -380, -380, -380, -380, -380, -380, -380, 0, 0, 0, -380, -380, -380, -380, -380, 0, -380, -380, -380, -380, -380, -380, -380, -380, -380, -380, -380, -380, -380, 0, 0, 0, 0, -380, -380, -380, -380, -380, 0, -380, 0, 0, 0, 0, 0, 0, 0, 0, -380, 0, 0, -380, -380, 0, -380, 0, -380, -380, 0, 0, 0, -380, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, -380, -380, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -382, -382, -382, -382, -382, -382, 0, -382, -382, 0, -382, -382, -382, -382, -382, -382, -382, 0, 0, 0, -382, -382, -382, -382, -382, 0, -382, -382, -382, -382, -382, -382, -382, -382, -382, -382, -382, -382, -382, -382, 0, 0, 0, 0, -382, -382, -382, -382, -382, 0, -382, 0, 0, 0, 0, 0, 0, 0, 0, -382, 0, 0, -382, -382, 0, -382, 0, -382, -382, 0, 0, 0, -382, -382, 0, 0, 0, 0, 0, 0, 0, 0, 0, -382, -382, -382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 448 - -184, -184, -184, 0, -184, 0, -184, -184, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -184, 74, 0, -184, -184, 0, -184, 0, -184, -184, -184, -184, 0, -184, 0, 0, 0, 0, -184, -184, -184, 0, -184, -184, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -186, -186, -186, 0, -186, 0, -186, -186, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -186, -501, 0, -186, -186, 0, -186, 0, -186, -186, -186, -186, 0, 0, -186, 0, 0, 0, 0, -186, -186, -186, 0, -186, -186, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 449 - 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -504, 0, 0, 0, 0, 0, 0, -504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 450 - 0, 0, 0, 0, 0, 0, 0, 537, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 451 - 0, 0, 0, 0, 0, 0, 0, -501, 0, 0, 0, 0, 0, 0, -501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 538, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 452 - 0, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -505, 0, 0, 0, 0, 0, 0, -505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 453 - 0, 0, 0, 0, 0, 0, 0, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 454 - -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, 0, -198, 0, -198, -198, -198, -198, -198, 0, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, 0, 0, 0, -198, -198, -198, -198, -198, -198, 0, -198, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, 0, -198, -198, 0, -198, 0, -198, -198, 0, 0, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 455 - -791, 0, 0, -791, 0, -791, 0, -791, 0, 0, -791, -791, 0, -791, -791, 0, -791, 0, 0, 0, 0, 0, -791, -791, -791, 0, -791, 0, 0, -791, 0, -791, 0, 0, 0, 0, -791, 0, -791, 0, 0, 0, 0, -791, 0, -791, 0, 0, 0, -791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -791, 0, 0, 0, 0, -791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, -791, -791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, 0, -200, 0, -200, -200, -200, -200, -200, 0, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, 0, 0, 0, -200, -200, -200, -200, -200, -200, 0, -200, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, 0, -200, -200, 0, -200, 0, -200, -200, 0, 0, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 456 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -796, 0, 0, -796, 0, -796, 0, -796, 0, 0, -796, -796, 0, -796, -796, 0, -796, 0, 0, 0, 0, 0, -796, -796, -796, 0, -796, 0, 0, -796, 0, -796, 0, 0, 0, 0, -796, 0, 0, -796, 0, 0, 0, 0, -796, 0, -796, 0, 0, 0, -796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -796, 0, 0, 0, 0, -796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, -796, -796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 457 - -498, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 458 - 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -502, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 459 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 460 - 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 461 - -499, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 462 - -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, 0, -186, 0, -186, -186, -186, -186, -186, 0, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, -186, 0, 0, 0, -186, -186, -186, -186, -186, -186, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, -186, -186, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -503, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 463 - -246, -246, -246, -246, -246, -246, 22, -246, -246, -246, -246, -246, -246, -246, -246, -246, -246, 0, 23, 0, -246, -246, -246, -246, -246, 0, -246, -246, -246, -246, -246, -246, -246, -246, -246, -246, -246, -246, -246, 0, 0, 0, 24, -246, -246, -246, -246, -246, 0, -246, 0, 0, 0, 0, 0, 0, 0, 0, -246, 0, 0, -246, -246, 0, -246, 0, -246, -246, 0, 0, 0, -246, -246, 0, 0, 0, 0, 0, 0, 0, 0, 0, -246, -246, -246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 0, -188, 0, -188, -188, -188, -188, -188, 0, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 0, 0, 0, -188, -188, -188, -188, -188, -188, 0, -188, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, 0, -188, -188, 0, -188, 0, -188, -188, 0, 0, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 464 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 465 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, -710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 0, 0, 0, 0, -714, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 466 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, -684, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, -688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 467 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -527, 0, 0, 0, 0, 0, 0, 0, 0, 0, -527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 468 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 469 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -547, 0, 0, 0, 0, 0, 0, 0, 0, 0, -547, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -551, 0, 0, 0, 0, 0, 0, 0, 0, 0, -551, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 470 - -503, 0, 0, -503, 0, -503, 0, -503, 0, 0, -503, -503, 0, -503, -503, 0, -503, 0, 0, 0, 0, 0, -503, -503, -503, 0, -503, 0, 0, -503, 0, -503, 0, 0, 0, 0, -503, 0, -503, 0, 0, 0, 0, -503, 0, -503, -503, -503, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, -503, -503, 0, -503, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -507, 0, 0, -507, 0, -507, 0, -507, 0, 0, -507, -507, 0, -507, -507, 0, -507, 0, 0, 0, 0, 0, -507, -507, -507, 0, -507, 0, 0, -507, 0, -507, 0, 0, 0, 0, -507, 0, 0, -507, 0, 0, 0, 0, -507, 0, -507, -507, -507, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, -507, -507, 0, -507, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 471 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 472 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 473 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 474 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 475 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 552, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 476 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 477 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 478 - -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, 0, -203, 0, -203, -203, -203, -203, -203, 0, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, 0, 0, 0, -203, -203, -203, -203, -203, -203, 0, -203, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, 0, -203, -203, 0, -203, 0, -203, -203, 0, 0, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, 0, -205, 0, -205, -205, -205, -205, -205, 0, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, 0, 0, 0, -205, -205, -205, -205, -205, -205, 0, -205, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, 0, -205, -205, 0, -205, 0, -205, -205, 0, 0, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 479 - -788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 480 - -325, 0, 0, 0, 0, 0, -325, 0, -325, 0, 0, 0, -325, 0, 0, -325, 0, 0, 0, -325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -325, 0, -325, -325, -325, -325, 0, 0, 0, 0, 0, -325, -325, -325, -325, 0, -325, -325, -325, -325, 0, 0, 0, 0, -325, -325, -325, -325, -325, 0, 0, -325, -325, -325, -325, 0, -325, -325, -325, -325, -325, -325, -325, -325, -325, 0, 0, 0, -325, -325, 0, 0, 0, -325, -325, -325, -325, -325, -325, + -327, 0, 0, 0, 0, 0, -327, 0, -327, 0, 0, 0, -327, 0, 0, -327, 0, 0, 0, -327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -327, 0, -327, -327, -327, -327, 0, 0, 0, 0, 0, -327, -327, -327, -327, 0, -327, -327, -327, -327, 0, 0, 0, 0, -327, -327, -327, -327, -327, 0, 0, -327, -327, -327, -327, 0, -327, -327, -327, -327, -327, -327, -327, -327, -327, 0, 0, 0, -327, -327, 0, 0, 0, -327, -327, -327, -327, -327, -327, // State 481 - -745, 0, 0, 0, 0, 0, -745, 0, -745, 0, 0, 0, -745, 0, 0, -745, 0, 0, 0, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -745, 0, -745, -745, -745, -745, 0, 0, 0, 0, 0, -745, -745, -745, -745, 0, -745, -745, -745, -745, 0, 0, 0, 0, -745, -745, -745, -745, -745, 0, 0, -745, -745, -745, -745, 0, -745, -745, -745, -745, -745, -745, -745, -745, -745, 0, 0, 0, -745, 0, 0, 0, 0, -745, -745, -745, -745, -745, -745, + -749, 0, 0, 0, 0, 0, -749, 0, -749, 0, 0, 0, -749, 0, 0, -749, 0, 0, 0, -749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -749, 0, -749, -749, -749, -749, 0, 0, 0, 0, 0, -749, -749, -749, -749, 0, -749, -749, -749, -749, 0, 0, 0, 0, -749, -749, -749, -749, -749, 0, 0, -749, -749, -749, -749, 0, -749, -749, -749, -749, -749, -749, -749, -749, -749, 0, 0, 0, -749, 0, 0, 0, 0, -749, -749, -749, -749, -749, -749, // State 482 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -340, 0, 0, 0, -340, 0, -340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -342, 0, 0, 0, -342, 0, -342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 483 - -783, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -783, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 484 - -781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 485 - -784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 486 - -321, 0, 0, 0, 0, 0, -321, 0, -321, 0, 0, 0, -321, 0, 0, -321, 0, 0, 0, -321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -321, 0, -321, -321, -321, -321, 0, 0, 0, 0, 0, -321, -321, -321, -321, 0, -321, -321, -321, -321, 0, 0, 0, 0, -321, -321, -321, -321, -321, 0, 0, -321, -321, -321, -321, 0, -321, -321, -321, -321, -321, -321, -321, -321, -321, 0, 0, 0, -321, -321, 0, 0, 0, -321, -321, -321, -321, -321, -321, + -323, 0, 0, 0, 0, 0, -323, 0, -323, 0, 0, 0, -323, 0, 0, -323, 0, 0, 0, -323, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -323, 0, -323, -323, -323, -323, 0, 0, 0, 0, 0, -323, -323, -323, -323, 0, -323, -323, -323, -323, 0, 0, 0, 0, -323, -323, -323, -323, -323, 0, 0, -323, -323, -323, -323, 0, -323, -323, -323, -323, -323, -323, -323, -323, -323, 0, 0, 0, -323, -323, 0, 0, 0, -323, -323, -323, -323, -323, -323, // State 487 - -324, 0, 0, 0, 0, 0, -324, 0, -324, 0, 0, 0, -324, 0, 0, -324, 0, 0, 0, -324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -324, 0, -324, -324, -324, -324, 0, 0, 0, 0, 0, -324, -324, -324, -324, 0, -324, -324, -324, -324, 0, 0, 0, 0, -324, -324, -324, -324, -324, 0, 0, -324, -324, -324, -324, 0, -324, -324, -324, -324, -324, -324, -324, -324, -324, 0, 0, 0, -324, -324, 0, 0, 0, -324, -324, -324, -324, -324, -324, + -326, 0, 0, 0, 0, 0, -326, 0, -326, 0, 0, 0, -326, 0, 0, -326, 0, 0, 0, -326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -326, 0, -326, -326, -326, -326, 0, 0, 0, 0, 0, -326, -326, -326, -326, 0, -326, -326, -326, -326, 0, 0, 0, 0, -326, -326, -326, -326, -326, 0, 0, -326, -326, -326, -326, 0, -326, -326, -326, -326, -326, -326, -326, -326, -326, 0, 0, 0, -326, -326, 0, 0, 0, -326, -326, -326, -326, -326, -326, // State 488 - -786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -790, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -790, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 489 - -319, 0, 0, 0, 0, 0, -319, 0, -319, 0, 0, 0, -319, 0, 0, -319, 0, 0, 0, -319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -319, 0, -319, -319, -319, -319, 0, 0, 0, 0, 0, -319, -319, -319, -319, 0, -319, -319, -319, -319, 0, 0, 0, 0, -319, -319, -319, -319, -319, 0, 0, -319, -319, -319, -319, 0, -319, -319, -319, -319, -319, -319, -319, -319, -319, 0, 0, 0, -319, -319, 0, 0, 0, -319, -319, -319, -319, -319, -319, + -321, 0, 0, 0, 0, 0, -321, 0, -321, 0, 0, 0, -321, 0, 0, -321, 0, 0, 0, -321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -321, 0, -321, -321, -321, -321, 0, 0, 0, 0, 0, -321, -321, -321, -321, 0, -321, -321, -321, -321, 0, 0, 0, 0, -321, -321, -321, -321, -321, 0, 0, -321, -321, -321, -321, 0, -321, -321, -321, -321, -321, -321, -321, -321, -321, 0, 0, 0, -321, -321, 0, 0, 0, -321, -321, -321, -321, -321, -321, // State 490 - -785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 491 - -790, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -790, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 492 - -318, 0, 0, 0, 0, 0, -318, 0, -318, 0, 0, 0, -318, 0, 0, -318, 0, 0, 0, -318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -318, 0, -318, -318, -318, -318, 0, 0, 0, 0, 0, -318, -318, -318, -318, 0, -318, -318, -318, -318, 0, 0, 0, 0, -318, -318, -318, -318, -318, 0, 0, -318, -318, -318, -318, 0, -318, -318, -318, -318, -318, -318, -318, -318, -318, 0, 0, 0, -318, -318, 0, 0, 0, -318, -318, -318, -318, -318, -318, + -795, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -795, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 493 - -787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -320, 0, 0, 0, 0, 0, -320, 0, -320, 0, 0, 0, -320, 0, 0, -320, 0, 0, 0, -320, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -320, 0, -320, -320, -320, -320, 0, 0, 0, 0, 0, -320, -320, -320, -320, 0, -320, -320, -320, -320, 0, 0, 0, 0, -320, -320, -320, -320, -320, 0, 0, -320, -320, -320, -320, 0, -320, -320, -320, -320, -320, -320, -320, -320, -320, 0, 0, 0, -320, -320, 0, 0, 0, -320, -320, -320, -320, -320, -320, // State 494 - -782, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -782, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 495 - -389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 496 - 570, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -391, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -391, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 497 - -845, 0, 0, -845, 0, -845, 0, 0, 0, 0, -845, -845, 0, -845, -845, 0, -845, 0, 0, 0, 0, 0, -845, -845, 94, 0, -845, 0, 0, -845, 0, -845, 0, 0, 0, 0, -845, 0, -845, 0, 0, 0, 0, 0, 0, -845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 573, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 498 - -322, 0, 0, 0, 0, 0, -322, 0, -322, 0, 0, 0, -322, 0, 0, -322, 0, 0, 0, -322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -322, 0, -322, -322, -322, -322, 0, 0, 0, 0, 0, -322, -322, -322, -322, 0, -322, -322, -322, -322, 0, 0, 0, 0, -322, -322, -322, -322, -322, 0, 0, -322, -322, -322, -322, 0, -322, -322, -322, -322, -322, -322, -322, -322, -322, 0, 0, 0, -322, -322, 0, 0, 0, -322, -322, -322, -322, -322, -322, + -850, 0, 0, -850, 0, -850, 0, 0, 0, 0, -850, -850, 0, -850, -850, 0, -850, 0, 0, 0, 0, 0, -850, -850, 97, 0, -850, 0, 0, -850, 0, -850, 0, 0, 0, 0, -850, 0, 0, -850, 0, 0, 0, 0, 0, 0, -850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 499 - -789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -324, 0, 0, 0, 0, 0, -324, 0, -324, 0, 0, 0, -324, 0, 0, -324, 0, 0, 0, -324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -324, 0, -324, -324, -324, -324, 0, 0, 0, 0, 0, -324, -324, -324, -324, 0, -324, -324, -324, -324, 0, 0, 0, 0, -324, -324, -324, -324, -324, 0, 0, -324, -324, -324, -324, 0, -324, -324, -324, -324, -324, -324, -324, -324, -324, 0, 0, 0, -324, -324, 0, 0, 0, -324, -324, -324, -324, -324, -324, // State 500 - -320, 0, 0, 0, 0, 0, -320, 0, -320, 0, 0, 0, -320, 0, 0, -320, 0, 0, 0, -320, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -320, 0, -320, -320, -320, -320, 0, 0, 0, 0, 0, -320, -320, -320, -320, 0, -320, -320, -320, -320, 0, 0, 0, 0, -320, -320, -320, -320, -320, 0, 0, -320, -320, -320, -320, 0, -320, -320, -320, -320, -320, -320, -320, -320, -320, 0, 0, 0, -320, -320, 0, 0, 0, -320, -320, -320, -320, -320, -320, + -793, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -793, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 501 - -323, 0, 0, 0, 0, 0, -323, 0, -323, 0, 0, 0, -323, 0, 0, -323, 0, 0, 0, -323, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -323, 0, -323, -323, -323, -323, 0, 0, 0, 0, 0, -323, -323, -323, -323, 0, -323, -323, -323, -323, 0, 0, 0, 0, -323, -323, -323, -323, -323, 0, 0, -323, -323, -323, -323, 0, -323, -323, -323, -323, -323, -323, -323, -323, -323, 0, 0, 0, -323, -323, 0, 0, 0, -323, -323, -323, -323, -323, -323, + -322, 0, 0, 0, 0, 0, -322, 0, -322, 0, 0, 0, -322, 0, 0, -322, 0, 0, 0, -322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -322, 0, -322, -322, -322, -322, 0, 0, 0, 0, 0, -322, -322, -322, -322, 0, -322, -322, -322, -322, 0, 0, 0, 0, -322, -322, -322, -322, -322, 0, 0, -322, -322, -322, -322, 0, -322, -322, -322, -322, -322, -322, -322, -322, -322, 0, 0, 0, -322, -322, 0, 0, 0, -322, -322, -322, -322, -322, -322, // State 502 - -388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -325, 0, 0, 0, 0, 0, -325, 0, -325, 0, 0, 0, -325, 0, 0, -325, 0, 0, 0, -325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -325, 0, -325, -325, -325, -325, 0, 0, 0, 0, 0, -325, -325, -325, -325, 0, -325, -325, -325, -325, 0, 0, 0, 0, -325, -325, -325, -325, -325, 0, 0, -325, -325, -325, -325, 0, -325, -325, -325, -325, -325, -325, -325, -325, -325, 0, 0, 0, -325, -325, 0, 0, 0, -325, -325, -325, -325, -325, -325, // State 503 - -750, 0, 0, 0, 0, 0, -750, 0, -750, 0, 0, 0, -750, 0, 0, -750, 0, 0, 0, -750, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -750, 0, -750, -750, -750, -750, 0, 0, 0, 0, 0, -750, -750, -750, -750, 0, -750, -750, -750, -750, 0, 0, 0, 0, -750, -750, -750, -750, -750, 0, 0, -750, -750, -750, -750, 0, -750, -750, -750, -750, -750, -750, -750, -750, -750, 0, 0, 0, -750, 0, 0, 0, 0, -750, -750, -750, -750, -750, -750, + -390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 504 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -754, 0, 0, 0, 0, 0, -754, 0, -754, 0, 0, 0, -754, 0, 0, -754, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -754, 0, -754, -754, -754, -754, 0, 0, 0, 0, 0, -754, -754, -754, -754, 0, -754, -754, -754, -754, 0, 0, 0, 0, -754, -754, -754, -754, -754, 0, 0, -754, -754, -754, -754, 0, -754, -754, -754, -754, -754, -754, -754, -754, -754, 0, 0, 0, -754, 0, 0, 0, 0, -754, -754, -754, -754, -754, -754, // State 505 - -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 506 - -385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 507 - -731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 508 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 509 - -454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 510 - 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, -112, 0, 0, -112, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, -112, -112, -112, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, -112, 0, 0, 0, 0, -112, -112, -112, 0, -112, -112, + -450, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -450, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 511 - 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, -120, 0, 0, -120, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, -120, -120, -120, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, -120, 0, 0, 0, 0, -120, -120, -120, 0, -120, -120, + 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, -112, 0, 0, -112, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, -112, -112, -112, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, -112, 0, 0, 0, 0, -112, -112, -112, 0, -112, -112, // State 512 - 0, 0, 0, 0, 0, 0, 0, 632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, -120, 0, 0, -120, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, -120, -120, -120, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, 0, -120, 0, 0, 0, -120, 0, 0, 0, 0, -120, -120, -120, 0, -120, -120, // State 513 - 0, 0, 0, 0, 0, 0, 0, -163, 0, 0, 0, 0, 0, 0, 633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 636, 0, 0, 0, 0, 0, 0, 637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 514 - 0, -184, -184, 0, -184, 0, -184, -184, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, 0, 74, 0, -184, -184, 0, -184, 117, -184, -184, -184, -184, 0, -184, 0, 0, 0, 0, -184, 0, -184, 0, -184, 0, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -186, -186, 0, -186, 0, -186, -186, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, 0, -501, 0, -186, -186, 0, -186, 121, -186, -186, -186, -186, 0, 0, -186, 0, 0, 0, 0, -186, 0, -186, 0, -186, 0, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 515 - -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, 0, -241, 0, -241, -241, -241, -241, -241, 0, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, -241, 0, 0, 0, -241, -241, -241, -241, -241, -241, 0, -241, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, 0, -241, -241, 0, -241, 0, -241, -241, 0, 0, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, 0, -164, 0, -164, -164, -164, -164, -164, 0, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, 0, 0, 0, -164, -164, -164, -164, -164, -164, 0, -164, 0, 0, 0, 0, 0, 0, 0, 0, -164, 0, 0, -164, -164, 0, -164, 0, -164, -164, 0, 0, 0, -164, -164, 0, 0, 0, 0, 0, 0, 0, 0, 0, -164, -164, -164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 516 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, 0, -243, 0, -243, -243, -243, -243, -243, 0, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, -243, 0, 0, 0, -243, -243, -243, -243, -243, -243, 0, -243, 0, 0, 0, 0, 0, 0, 0, 0, -243, 0, 0, -243, -243, 0, -243, 0, -243, -243, 0, 0, 0, -243, -243, 0, 0, 0, 0, 0, 0, 0, 0, 0, -243, -243, -243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 517 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 518 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 519 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 520 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 521 - -740, -740, -740, -740, -740, -740, 0, -740, -740, 0, -740, -740, -740, -740, -740, -740, -740, 0, 0, 0, -740, -740, -740, -740, -740, 0, -740, -740, -740, -740, -740, -740, -740, -740, -740, -740, -740, -740, -740, 0, 0, 0, 0, -740, -740, -740, -740, -740, 0, -740, 0, 0, 0, 0, 0, 0, 0, 0, -740, 0, 0, -740, -740, 0, -740, 0, -740, -740, 0, 0, 0, -740, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, -740, -740, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -827, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 522 - -142, -142, 0, -142, 0, -142, 0, -142, 0, 0, -142, -142, 0, -142, -142, 0, -142, 0, 0, 0, 0, 0, -142, -142, -142, 0, -142, -142, 0, -142, -142, -142, -142, -142, -142, 0, -142, 0, -142, 0, 0, 0, 0, -142, 0, -142, -142, -142, 0, -142, 0, 0, 0, 0, 0, 0, 0, 0, -142, 0, 0, -142, -142, 0, -142, 0, -142, -142, 0, 0, 0, -142, -142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, -142, -142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -744, -744, -744, -744, -744, -744, 0, -744, -744, 0, -744, -744, -744, -744, -744, -744, -744, 0, 0, 0, -744, -744, -744, -744, -744, 0, -744, -744, -744, -744, -744, -744, -744, -744, -744, -744, -744, -744, -744, -744, 0, 0, 0, 0, -744, -744, -744, -744, -744, 0, -744, 0, 0, 0, 0, 0, 0, 0, 0, -744, 0, 0, -744, -744, 0, -744, 0, -744, -744, 0, 0, 0, -744, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, -744, -744, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 523 - 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, 0, 0, -313, 0, 0, -313, 0, 0, 0, -313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -313, -313, -313, -313, 0, 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, -313, 0, 0, 0, 0, -313, -313, -313, 0, -313, -313, + -142, -142, 0, -142, 0, -142, 0, -142, 0, 0, -142, -142, 0, -142, -142, 0, -142, 0, 0, 0, 0, 0, -142, -142, -142, 0, -142, -142, 0, -142, -142, -142, -142, -142, -142, 0, -142, 0, 0, -142, 0, 0, 0, 0, -142, 0, -142, -142, -142, 0, -142, 0, 0, 0, 0, 0, 0, 0, 0, -142, 0, 0, -142, -142, 0, -142, 0, -142, -142, 0, 0, 0, -142, -142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, -142, -142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 524 - 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, 0, 0, -311, 0, 0, -311, 0, 0, 0, -311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -311, -311, -311, -311, 0, 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -311, 0, 0, 0, -311, 0, 0, 0, 0, -311, -311, -311, 0, -311, -311, + 0, 0, 0, 0, 0, 0, -315, 0, 0, 0, 0, 0, -315, 0, 0, -315, 0, 0, 0, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -315, -315, -315, -315, 0, 0, 0, 0, 0, 0, 0, -315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -315, 0, 0, 0, -315, 0, 0, 0, 0, -315, -315, -315, 0, -315, -315, // State 525 - -365, -365, 0, -365, 0, -365, 0, -365, 0, 0, -365, -365, 0, -365, -365, 0, -365, 0, 0, 0, 0, 0, -365, -365, -365, 0, -365, -365, 0, -365, -365, -365, -365, -365, -365, 0, -365, 0, -365, 0, 0, 0, 0, -365, 33, -365, -365, -365, 0, -365, 0, 0, 0, 0, 0, 0, 0, 0, -365, 0, 0, -365, -365, 0, -365, 0, -365, -365, 0, 0, 0, -365, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, -365, -365, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, 0, 0, -313, 0, 0, -313, 0, 0, 0, -313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -313, -313, -313, -313, 0, 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -313, 0, 0, 0, -313, 0, 0, 0, 0, -313, -313, -313, 0, -313, -313, // State 526 - -89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -367, -367, 0, -367, 0, -367, 0, -367, 0, 0, -367, -367, 0, -367, -367, 0, -367, 0, 0, 0, 0, 0, -367, -367, -367, 0, -367, -367, 0, -367, -367, -367, -367, -367, -367, 0, -367, -367, 0, -367, 0, 0, 0, 0, -367, 34, -367, -367, -367, 0, -367, 0, 0, 0, 0, 0, 0, 0, 0, -367, 0, 0, -367, -367, 0, -367, 0, -367, -367, 0, 0, 0, -367, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, -367, -367, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 527 - -534, 0, 0, -534, 0, -534, 0, -534, 0, 0, -534, -534, 0, -534, -534, 0, -534, 0, 0, 0, 0, 0, -534, -534, -534, 0, -534, 0, 0, -534, 0, -534, 0, 0, 0, 0, -534, 0, -534, 0, 0, 0, 0, 0, 0, -534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 528 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -538, 0, 0, -538, 0, -538, 0, -538, 0, 0, -538, -538, 0, -538, -538, 0, -538, 0, 0, 0, 0, 0, -538, -538, -538, 0, -538, 0, 0, -538, 0, -538, 0, 0, 0, 0, -538, 0, 0, -538, 0, 0, 0, 0, 0, 0, -538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 529 - -828, -828, -828, -828, -828, -828, 0, -828, -828, 0, -828, -828, -828, -828, -828, -828, -828, 0, 0, 0, -828, -828, -828, -828, -828, 0, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, 0, 0, 0, 0, -828, -828, -828, -828, -828, 0, -828, 0, 0, 0, 0, 0, 0, 0, 0, -828, 0, 0, -828, -828, 0, -828, 0, -828, -828, 0, 0, 0, -828, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, -828, -828, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 530 - -910, -910, 0, -910, 20, -910, 0, -910, 0, 0, -910, -910, 0, -910, -910, 0, -910, 0, 0, 0, 0, 0, -910, -910, -910, 0, -910, -910, 0, -910, -910, -910, -910, -910, -910, 0, -910, 0, -910, 0, 0, 0, 0, -910, -910, -910, -910, -910, 0, -910, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, 0, -910, -910, 0, -910, 0, -910, -910, 0, 0, 0, -910, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, -910, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -833, -833, -833, -833, -833, -833, 0, -833, -833, 0, -833, -833, -833, -833, -833, -833, -833, 0, 0, 0, -833, -833, -833, -833, -833, 0, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, 0, 0, 0, 0, -833, -833, -833, -833, -833, 0, -833, 0, 0, 0, 0, 0, 0, 0, 0, -833, 0, 0, -833, -833, 0, -833, 0, -833, -833, 0, 0, 0, -833, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, -833, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 531 - 0, 0, 0, 0, 0, 0, 0, 641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -915, -915, 0, -915, 21, -915, 0, -915, 0, 0, -915, -915, 0, -915, -915, 0, -915, 0, 0, 0, 0, 0, -915, -915, -915, 0, -915, -915, 0, -915, -915, -915, -915, -915, -915, 0, -915, -915, 0, -915, 0, 0, 0, 0, -915, -915, -915, -915, -915, 0, -915, 0, 0, 0, 0, 0, 0, 0, 0, -915, 0, 0, -915, -915, 0, -915, 0, -915, -915, 0, 0, 0, -915, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, -915, -915, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 532 - 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 533 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -779, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 534 - 0, 0, 0, 0, 0, 0, 0, 644, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 535 - -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, 0, -195, 0, -195, -195, -195, -195, -195, 0, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, 0, 0, 0, -195, -195, -195, -195, -195, -195, 0, -195, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, 0, -195, -195, 0, -195, 0, -195, -195, 0, 0, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 648, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 536 - -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, 0, -189, 0, -189, -189, -189, -189, -189, 0, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, 0, 0, 0, -189, -189, -189, -189, -189, -189, 0, -189, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, 0, -189, -189, 0, -189, 0, -189, -189, 0, 0, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, 0, -197, 0, -197, -197, -197, -197, -197, 0, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, 0, 0, 0, -197, -197, -197, -197, -197, -197, 0, -197, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, 0, -197, -197, 0, -197, 0, -197, -197, 0, 0, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 537 - -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, 0, -199, 0, -199, -199, -199, -199, -199, 0, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, 0, 0, 0, -199, -199, -199, -199, -199, -199, 0, -199, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, 0, -199, -199, 0, -199, 0, -199, -199, 0, 0, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, 0, -191, 0, -191, -191, -191, -191, -191, 0, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, 0, 0, 0, -191, -191, -191, -191, -191, -191, 0, -191, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, 0, -191, -191, 0, -191, 0, -191, -191, 0, 0, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 538 - 0, 0, 0, 0, 0, 0, 0, 650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, 0, -201, 0, -201, -201, -201, -201, -201, 0, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, 0, 0, 0, -201, -201, -201, -201, -201, -201, 0, -201, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, 0, -201, -201, 0, -201, 0, -201, -201, 0, 0, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 539 - -914, 0, 0, 0, 0, 0, 0, -914, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -914, 0, 0, 0, 0, -914, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 540 - -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, 0, -185, 0, -185, -185, -185, -185, -185, 0, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, -185, 0, 0, 0, -185, -185, -185, -185, -185, -185, 0, -185, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, 0, -185, -185, 0, -185, 0, -185, -185, 0, 0, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -919, 0, 0, 0, 0, 0, 0, -919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -919, 0, 0, 0, 0, -919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 541 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 653, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, 0, -187, 0, -187, -187, -187, -187, -187, 0, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, 0, 0, 0, -187, -187, -187, -187, -187, -187, 0, -187, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, 0, -187, -187, 0, -187, 0, -187, -187, 0, 0, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 542 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 657, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 543 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, -708, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -713, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 544 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, -712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 545 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -802, 0, 0, 0, 0, 0, 0, 0, 0, 0, -802, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 546 - -452, 0, 0, -452, 0, -452, 0, -452, 0, 0, -452, -452, 0, -452, -452, 0, -452, 0, 0, 0, 0, 0, -452, -452, -452, 0, -452, 0, 0, -452, 0, -452, 0, 0, 0, 0, -452, 0, -452, 0, 0, 0, 0, -452, 0, -452, 0, -452, 0, -452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452, -452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452, -452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 547 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -457, 0, 0, -457, 0, -457, 0, -457, 0, 0, -457, -457, 0, -457, -457, 0, -457, 0, 0, 0, 0, 0, -457, -457, -457, 0, -457, 0, 0, -457, 0, -457, 0, 0, 0, 0, -457, 0, 0, -457, 0, 0, 0, 0, -457, 0, -457, 0, -457, 0, -457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457, -457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457, -457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 548 - -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 0, -202, 0, -202, -202, -202, -202, -202, 0, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 0, 0, 0, -202, -202, -202, -202, -202, -202, 0, -202, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, -202, -202, 0, -202, 0, -202, -202, 0, 0, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 549 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, 0, -204, 0, -204, -204, -204, -204, -204, 0, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, 0, 0, 0, -204, -204, -204, -204, -204, -204, 0, -204, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, 0, -204, -204, 0, -204, 0, -204, -204, 0, 0, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 550 - -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, 0, -205, 0, -205, -205, -205, -205, -205, 0, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, -205, 0, 0, 0, -205, -205, -205, -205, -205, -205, 0, -205, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, 0, -205, -205, 0, -205, 0, -205, -205, 0, 0, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 551 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, -344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, 0, -207, 0, -207, -207, -207, -207, -207, 0, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, -207, 0, 0, 0, -207, -207, -207, -207, -207, -207, 0, -207, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, 0, -207, -207, 0, -207, 0, -207, -207, 0, 0, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 552 - 667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, -346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 553 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -341, 0, 0, 0, -341, 0, -341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 554 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, -343, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 555 - -178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -178, 0, 0, 0, 0, -178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 556 - 0, 0, 0, 0, 0, 0, -255, 0, -255, 0, 0, 0, -255, 0, 0, -255, 0, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, -255, -255, -255, 0, 0, 0, 0, 0, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, -255, -255, 0, 0, 0, -255, 0, 0, 0, 0, -255, -255, -255, 0, -255, -255, + -451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 557 - 0, 0, 0, 0, 0, 0, -256, 0, -256, 0, 0, 0, -256, 0, 0, -256, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, -256, -256, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 0, 0, 0, -256, 0, 0, 0, 0, -256, -256, -256, 0, -256, -256, + -83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 558 - 0, 0, 0, 0, 0, 0, -261, 0, -261, 0, 0, 0, -261, 0, 0, -261, 0, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -261, -261, -261, -261, 0, 0, 0, 0, 0, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -261, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, -261, -261, 0, 0, 0, -261, 0, 0, 0, 0, -261, -261, -261, 0, -261, -261, + -180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -180, 0, 0, 0, 0, -180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 559 - 0, 0, 0, 0, 0, 0, -252, 0, -252, 0, 0, 0, -252, 0, 0, -252, 0, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -252, -252, -252, -252, 0, 0, 0, 0, 0, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -252, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, -252, -252, 0, 0, 0, -252, 0, 0, 0, 0, -252, -252, -252, 0, -252, -252, + 0, 0, 0, 0, 0, 0, -257, 0, -257, 0, 0, 0, -257, 0, 0, -257, 0, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -257, -257, -257, -257, 0, 0, 0, 0, 0, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -257, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, -257, -257, 0, 0, 0, -257, 0, 0, 0, 0, -257, -257, -257, 0, -257, -257, // State 560 - 0, 0, 0, 0, 0, 0, -250, 0, -250, 0, 0, 0, -250, 0, 0, -250, 0, 0, 0, -250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -250, -250, -250, -250, 0, 0, 0, 0, 0, 0, 0, -250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -250, 0, 0, -250, 0, 0, 0, 0, 0, 0, 0, 0, -250, -250, 0, 0, 0, -250, 0, 0, 0, 0, -250, -250, -250, 0, -250, -250, + 0, 0, 0, 0, 0, 0, -258, 0, -258, 0, 0, 0, -258, 0, 0, -258, 0, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -258, -258, -258, -258, 0, 0, 0, 0, 0, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -258, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, -258, -258, 0, 0, 0, -258, 0, 0, 0, 0, -258, -258, -258, 0, -258, -258, // State 561 - 0, 0, 0, 0, 0, 0, -251, 0, -251, 0, 0, 0, -251, 0, 0, -251, 0, 0, 0, -251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -251, -251, -251, -251, 0, 0, 0, 0, 0, 0, 0, -251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -251, 0, 0, -251, 0, 0, 0, 0, 0, 0, 0, 0, -251, -251, 0, 0, 0, -251, 0, 0, 0, 0, -251, -251, -251, 0, -251, -251, + 0, 0, 0, 0, 0, 0, -263, 0, -263, 0, 0, 0, -263, 0, 0, -263, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, -263, -263, -263, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, -263, -263, 0, 0, 0, -263, 0, 0, 0, 0, -263, -263, -263, 0, -263, -263, // State 562 - 0, 0, 0, 0, 0, 0, -262, 0, -262, 0, 0, 0, -262, 0, 0, -262, 0, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -262, -262, -262, -262, 0, 0, 0, 0, 0, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -262, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, -262, -262, 0, 0, 0, -262, 0, 0, 0, 0, -262, -262, -262, 0, -262, -262, + 0, 0, 0, 0, 0, 0, -254, 0, -254, 0, 0, 0, -254, 0, 0, -254, 0, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -254, -254, -254, -254, 0, 0, 0, 0, 0, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -254, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, -254, -254, 0, 0, 0, -254, 0, 0, 0, 0, -254, -254, -254, 0, -254, -254, // State 563 - 0, 0, 0, 0, 0, 0, -254, 0, -254, 0, 0, 0, -254, 0, 0, -254, 0, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -254, -254, -254, -254, 0, 0, 0, 0, 0, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -254, 0, 0, -254, 0, 0, 0, 0, 0, 0, 0, 0, -254, -254, 0, 0, 0, -254, 0, 0, 0, 0, -254, -254, -254, 0, -254, -254, + 0, 0, 0, 0, 0, 0, -252, 0, -252, 0, 0, 0, -252, 0, 0, -252, 0, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -252, -252, -252, -252, 0, 0, 0, 0, 0, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -252, 0, 0, -252, 0, 0, 0, 0, 0, 0, 0, 0, -252, -252, 0, 0, 0, -252, 0, 0, 0, 0, -252, -252, -252, 0, -252, -252, // State 564 - 0, 0, 0, 0, 0, 0, -259, 0, -259, 0, 0, 0, -259, 0, 0, -259, 0, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -259, -259, -259, -259, 0, 0, 0, 0, 0, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -259, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, -259, -259, 0, 0, 0, -259, 0, 0, 0, 0, -259, -259, -259, 0, -259, -259, + 0, 0, 0, 0, 0, 0, -253, 0, -253, 0, 0, 0, -253, 0, 0, -253, 0, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -253, -253, -253, -253, 0, 0, 0, 0, 0, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -253, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, -253, -253, 0, 0, 0, -253, 0, 0, 0, 0, -253, -253, -253, 0, -253, -253, // State 565 - 0, 0, 0, 0, 0, 0, -260, 0, -260, 0, 0, 0, -260, 0, 0, -260, 0, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -260, -260, -260, -260, 0, 0, 0, 0, 0, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -260, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, -260, -260, 0, 0, 0, -260, 0, 0, 0, 0, -260, -260, -260, 0, -260, -260, + 0, 0, 0, 0, 0, 0, -264, 0, -264, 0, 0, 0, -264, 0, 0, -264, 0, 0, 0, -264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -264, -264, -264, -264, 0, 0, 0, 0, 0, 0, 0, -264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -264, 0, 0, -264, 0, 0, 0, 0, 0, 0, 0, 0, -264, -264, 0, 0, 0, -264, 0, 0, 0, 0, -264, -264, -264, 0, -264, -264, // State 566 - 0, 0, 0, 0, 0, 0, -253, 0, -253, 0, 0, 0, -253, 0, 0, -253, 0, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -253, -253, -253, -253, 0, 0, 0, 0, 0, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -253, 0, 0, -253, 0, 0, 0, 0, 0, 0, 0, 0, -253, -253, 0, 0, 0, -253, 0, 0, 0, 0, -253, -253, -253, 0, -253, -253, + 0, 0, 0, 0, 0, 0, -256, 0, -256, 0, 0, 0, -256, 0, 0, -256, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, -256, -256, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 0, 0, 0, -256, 0, 0, 0, 0, -256, -256, -256, 0, -256, -256, // State 567 - 0, 0, 0, 0, 0, 0, -258, 0, -258, 0, 0, 0, -258, 0, 0, -258, 0, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -258, -258, -258, -258, 0, 0, 0, 0, 0, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -258, 0, 0, -258, 0, 0, 0, 0, 0, 0, 0, 0, -258, -258, 0, 0, 0, -258, 0, 0, 0, 0, -258, -258, -258, 0, -258, -258, + 0, 0, 0, 0, 0, 0, -261, 0, -261, 0, 0, 0, -261, 0, 0, -261, 0, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -261, -261, -261, -261, 0, 0, 0, 0, 0, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -261, 0, 0, -261, 0, 0, 0, 0, 0, 0, 0, 0, -261, -261, 0, 0, 0, -261, 0, 0, 0, 0, -261, -261, -261, 0, -261, -261, // State 568 - 0, 0, 0, 0, 0, 0, -257, 0, -257, 0, 0, 0, -257, 0, 0, -257, 0, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -257, -257, -257, -257, 0, 0, 0, 0, 0, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -257, 0, 0, -257, 0, 0, 0, 0, 0, 0, 0, 0, -257, -257, 0, 0, 0, -257, 0, 0, 0, 0, -257, -257, -257, 0, -257, -257, + 0, 0, 0, 0, 0, 0, -262, 0, -262, 0, 0, 0, -262, 0, 0, -262, 0, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -262, -262, -262, -262, 0, 0, 0, 0, 0, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -262, 0, 0, -262, 0, 0, 0, 0, 0, 0, 0, 0, -262, -262, 0, 0, 0, -262, 0, 0, 0, 0, -262, -262, -262, 0, -262, -262, // State 569 - -748, 0, 0, 0, 0, 0, -748, 0, -748, 0, 0, 0, -748, 0, 0, -748, 0, 0, 0, -748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -748, 0, -748, -748, -748, -748, 0, 0, 0, 0, 0, -748, -748, -748, -748, 0, -748, -748, -748, -748, 0, 0, 0, 0, -748, -748, -748, -748, -748, 0, 0, -748, -748, -748, -748, 0, -748, -748, -748, -748, -748, -748, -748, -748, -748, 0, 0, 0, -748, 0, 0, 0, 0, -748, -748, -748, -748, -748, -748, + 0, 0, 0, 0, 0, 0, -255, 0, -255, 0, 0, 0, -255, 0, 0, -255, 0, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, -255, -255, -255, 0, 0, 0, 0, 0, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, 0, 0, -255, 0, 0, 0, 0, 0, 0, 0, 0, -255, -255, 0, 0, 0, -255, 0, 0, 0, 0, -255, -255, -255, 0, -255, -255, // State 570 - 676, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, + 0, 0, 0, 0, 0, 0, -260, 0, -260, 0, 0, 0, -260, 0, 0, -260, 0, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -260, -260, -260, -260, 0, 0, 0, 0, 0, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -260, 0, 0, -260, 0, 0, 0, 0, 0, 0, 0, 0, -260, -260, 0, 0, 0, -260, 0, 0, 0, 0, -260, -260, -260, 0, -260, -260, // State 571 - 677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -259, 0, -259, 0, 0, 0, -259, 0, 0, -259, 0, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -259, -259, -259, -259, 0, 0, 0, 0, 0, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -259, 0, 0, -259, 0, 0, 0, 0, 0, 0, 0, 0, -259, -259, 0, 0, 0, -259, 0, 0, 0, 0, -259, -259, -259, 0, -259, -259, // State 572 - -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -752, 0, 0, 0, 0, 0, -752, 0, -752, 0, 0, 0, -752, 0, 0, -752, 0, 0, 0, -752, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -752, 0, -752, -752, -752, -752, 0, 0, 0, 0, 0, -752, -752, -752, -752, 0, -752, -752, -752, -752, 0, 0, 0, 0, -752, -752, -752, -752, -752, 0, 0, -752, -752, -752, -752, 0, -752, -752, -752, -752, -752, -752, -752, -752, -752, 0, 0, 0, -752, 0, 0, 0, 0, -752, -752, -752, -752, -752, -752, // State 573 - -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 681, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, // State 574 - -342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 575 - -509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 576 - -371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 577 - -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 578 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 579 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 580 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -418, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 581 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 582 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -440, -440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -440, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 583 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 584 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -437, -437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -437, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 585 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -436, -436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -436, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442, -442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442, 0, // State 586 - -511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 587 - -421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -439, -439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -439, 0, // State 588 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -438, -438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -438, 0, // State 589 - -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 590 - -445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 591 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 592 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 593 - -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 594 - -753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 690, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 595 - -386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 596 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 597 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 598 - 0, -182, -182, 0, -182, 0, -182, 0, -182, -182, 0, 0, -182, 0, -182, -182, 0, 0, -182, 0, -182, -182, 0, 0, -211, 0, 0, -182, -182, 0, -182, 0, -182, -182, -182, -182, 0, -182, 0, 0, 0, 0, -182, 0, -182, 0, -182, -182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -182, 0, -182, -182, 0, 0, 0, -182, -182, 0, 0, 0, 0, 0, 0, 0, 0, 0, -182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + -388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 599 - 0, -911, 0, 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, 0, -911, 0, -911, -911, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, -911, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, -911, -911, 0, 0, 0, -911, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 600 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -913, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 601 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -184, -184, 0, -184, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -213, 0, 0, -184, -184, 0, -184, 0, -184, -184, -184, -184, 0, 0, -184, 0, 0, 0, 0, -184, 0, -184, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 424, // State 602 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -916, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, 0, -916, 0, -916, -916, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, -916, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, -916, -916, 0, 0, 0, -916, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 603 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 604 - 0, -247, -247, 0, -247, 0, 160, 0, -247, -247, 0, 0, -247, 0, -247, -247, 0, 0, 161, 0, -247, -247, 0, 0, 0, 0, 0, -247, -247, 0, -247, 0, -247, -247, -247, -247, 0, -247, 0, 0, 0, 0, 162, 0, -247, 0, -247, -247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, 0, -247, -247, 0, 0, 0, -247, -247, 0, 0, 0, 0, 0, 0, 0, 0, 0, -247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 605 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 606 - 0, -741, -741, 0, -741, 0, 0, 0, -741, 163, 0, 0, -741, 0, -741, -741, 0, 0, 0, 0, -741, -741, 0, 0, 0, 0, 0, -741, -741, 0, -741, 0, -741, -741, -741, -741, 0, -741, 0, 0, 0, 0, 0, 0, -741, 0, -741, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -741, 0, -741, -741, 0, 0, 0, -741, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, -741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 607 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 608 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -745, -745, 0, -745, 0, 0, 0, -745, 166, 0, 0, -745, 0, -745, -745, 0, 0, 0, 0, -745, -745, 0, 0, 0, 0, 0, -745, -745, 0, -745, 0, -745, -745, -745, -745, 0, 0, -745, 0, 0, 0, 0, 0, 0, -745, 0, -745, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -745, 0, -745, -745, 0, 0, 0, -745, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, -745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 609 - 0, -183, -183, 0, -183, 0, -183, 0, -183, -183, 0, 0, -183, 0, -183, -183, 0, 0, -183, 0, -183, -183, 0, 0, -212, 0, 0, -183, -183, 0, -183, 0, -183, -183, -183, -183, 0, -183, 0, 0, 0, 0, -183, 0, -183, 0, -183, -183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -183, 0, -183, -183, 0, 0, 0, -183, -183, 0, 0, 0, 0, 0, 0, 0, 0, 0, -183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -747, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 610 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 611 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -831, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -185, -185, 0, -185, 0, -185, 0, -185, -185, 0, 0, -185, 0, -185, -185, 0, 0, -185, 0, -185, -185, 0, 0, -214, 0, 0, -185, -185, 0, -185, 0, -185, -185, -185, -185, 0, 0, -185, 0, 0, 0, 0, -185, 0, -185, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, -185, -185, 0, 0, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 612 - 0, -184, -184, 0, -184, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -184, 0, -184, -184, 0, 0, -213, 0, 0, -184, -184, 0, -184, 0, -184, -184, -184, -184, 0, -184, 0, 0, 0, 0, -184, 0, -184, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, -184, -184, 0, 0, 0, -184, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, -184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 613 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 614 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -186, -186, 0, -186, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -215, 0, 0, -186, -186, 0, -186, 0, -186, -186, -186, -186, 0, 0, -186, 0, 0, 0, 0, -186, 0, -186, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 615 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, -844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 616 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -838, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 617 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -838, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -838, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 618 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 619 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 620 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 621 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -893, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 622 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -895, 0, 0, 0, 0, 0, 0, -895, 0, 0, 0, 0, 0, 0, 0, 0, 0, -895, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 623 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 624 - 0, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, 0, -366, 0, -366, -366, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, -366, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, -366, -366, 0, 0, 0, -366, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 625 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -896, 0, 0, 0, 0, 0, 0, 0, 0, 0, -898, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 626 - 0, -210, -210, 0, -210, 0, -210, 0, -210, -210, 0, 0, -210, 0, -210, -210, 0, 0, -210, 0, -210, -210, 0, 0, -237, 0, 0, -210, -210, 0, -210, 0, -210, -210, -210, -210, 0, -210, 0, 0, 0, 0, -210, 0, -210, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, -210, -210, 0, 0, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 627 - 0, -208, -208, 0, -208, 0, -208, 0, -208, -208, 0, 0, -208, 0, -208, -208, 0, 0, -208, 0, -208, -208, 0, 0, -235, 0, 0, -208, -208, 0, -208, 0, -208, -208, -208, -208, 0, -208, 0, 0, 0, 0, -208, 0, -208, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, -208, -208, 0, 0, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, 0, -368, 0, -368, -368, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 0, -368, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, -368, -368, 0, 0, 0, -368, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, -368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 628 - 0, -209, -209, 0, -209, 0, -209, 0, -209, -209, 0, 0, -209, 0, -209, -209, 0, 0, -209, 0, -209, -209, 0, 0, -236, 0, 0, -209, -209, 0, -209, 0, -209, -209, -209, -209, 0, -209, 0, 0, 0, 0, -209, 0, -209, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, -209, -209, 0, 0, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 629 - 0, -207, -207, 0, -207, 0, -207, 0, -207, -207, 0, 0, -207, 0, -207, -207, 0, 0, -207, 0, -207, -207, 0, 0, -234, 0, 0, -207, -207, 0, -207, 0, -207, -207, -207, -207, 0, -207, 0, 0, 0, 0, -207, 0, -207, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, -207, -207, 0, 0, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -212, -212, 0, -212, 0, -212, 0, -212, -212, 0, 0, -212, 0, -212, -212, 0, 0, -212, 0, -212, -212, 0, 0, -239, 0, 0, -212, -212, 0, -212, 0, -212, -212, -212, -212, 0, 0, -212, 0, 0, 0, 0, -212, 0, -212, 0, -212, -212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -212, 0, -212, -212, 0, 0, 0, -212, -212, 0, 0, 0, 0, 0, 0, 0, 0, 0, -212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 630 - 0, 0, 0, 0, 0, 0, 0, -165, 0, 0, 0, 0, 0, 0, 705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -210, -210, 0, -210, 0, -210, 0, -210, -210, 0, 0, -210, 0, -210, -210, 0, 0, -210, 0, -210, -210, 0, 0, -237, 0, 0, -210, -210, 0, -210, 0, -210, -210, -210, -210, 0, 0, -210, 0, 0, 0, 0, -210, 0, -210, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, -210, -210, 0, 0, 0, -210, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, -210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 631 - -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, 0, -239, 0, -239, -239, -239, -239, -239, 0, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, -239, 0, 0, 0, -239, -239, -239, -239, -239, -239, 0, -239, 0, 0, 0, 0, 0, 0, 0, 0, -239, 0, 0, -239, -239, 0, -239, 0, -239, -239, 0, 0, 0, -239, -239, 0, 0, 0, 0, 0, 0, 0, 0, 0, -239, -239, -239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -211, -211, 0, -211, 0, -211, 0, -211, -211, 0, 0, -211, 0, -211, -211, 0, 0, -211, 0, -211, -211, 0, 0, -238, 0, 0, -211, -211, 0, -211, 0, -211, -211, -211, -211, 0, 0, -211, 0, 0, 0, 0, -211, 0, -211, 0, -211, -211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -211, 0, -211, -211, 0, 0, 0, -211, -211, 0, 0, 0, 0, 0, 0, 0, 0, 0, -211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 632 - 0, 0, 0, 0, 0, 0, -116, -116, -116, -116, 0, 0, -116, 0, 0, -116, 0, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, -116, -116, -116, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, 0, -116, 0, 0, 0, 0, -116, -116, -116, 0, -116, -116, + 0, -209, -209, 0, -209, 0, -209, 0, -209, -209, 0, 0, -209, 0, -209, -209, 0, 0, -209, 0, -209, -209, 0, 0, -236, 0, 0, -209, -209, 0, -209, 0, -209, -209, -209, -209, 0, 0, -209, 0, 0, 0, 0, -209, 0, -209, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, -209, -209, 0, 0, 0, -209, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 633 - 0, 0, 0, 0, 0, 0, 0, -410, 0, 0, 0, 0, 0, 0, -410, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 710, 0, 0, 0, 0, 0, 0, 711, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 634 - 0, 0, 0, 0, 0, 0, 0, -413, 0, 0, 0, 0, 0, 0, -413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, 0, -166, 0, -166, -166, -166, -166, -166, 0, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, -166, 0, 0, 0, -166, -166, -166, -166, -166, -166, 0, -166, 0, 0, 0, 0, 0, 0, 0, 0, -166, 0, 0, -166, -166, 0, -166, 0, -166, -166, 0, 0, 0, -166, -166, 0, 0, 0, 0, 0, 0, 0, 0, 0, -166, -166, -166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 635 - 0, 0, 0, 0, 0, 0, 0, -414, 0, 0, 0, 0, 0, 0, -414, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, 0, -163, 0, -163, -163, -163, -163, -163, 0, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, -163, 0, 0, 0, -163, -163, -163, -163, -163, -163, 0, -163, 0, 0, 0, 0, 0, 0, 0, 0, -163, 0, 0, -163, -163, 0, -163, 0, -163, -163, 0, 0, 0, -163, -163, 0, 0, 0, 0, 0, 0, 0, 0, 0, -163, -163, -163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 636 - -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, 0, -240, 0, -240, -240, -240, -240, -240, 0, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, -240, 0, 0, 0, -240, -240, -240, -240, -240, -240, 0, -240, 0, 0, 0, 0, 0, 0, 0, 0, -240, 0, 0, -240, -240, 0, -240, 0, -240, -240, 0, 0, 0, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -116, -116, -116, -116, 0, 0, -116, 0, 0, -116, 0, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, -116, -116, -116, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, 0, -116, 0, 0, 0, 0, -116, -116, -116, 0, -116, -116, // State 637 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -412, 0, 0, 0, 0, 0, 0, -412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 638 - -143, -143, 0, -143, 0, -143, 0, -143, 0, 0, -143, -143, 0, -143, -143, 0, -143, 0, 0, 0, 0, 0, -143, -143, -143, 0, -143, -143, 0, -143, -143, -143, -143, -143, -143, 0, -143, 0, -143, 0, 0, 0, 0, -143, 0, -143, -143, -143, 0, -143, 0, 0, 0, 0, 0, 0, 0, 0, -143, 0, 0, -143, -143, 0, -143, 0, -143, -143, 0, 0, 0, -143, -143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, -143, -143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -415, 0, 0, 0, 0, 0, 0, -415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 639 - -497, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -416, 0, 0, 0, 0, 0, 0, -416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 640 - -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, 0, -200, 0, -200, -200, -200, -200, -200, 0, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, 0, 0, 0, -200, -200, -200, -200, -200, -200, 0, -200, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, 0, -200, -200, 0, -200, 0, -200, -200, 0, 0, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, 0, -242, 0, -242, -242, -242, -242, -242, 0, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, 0, 0, 0, -242, -242, -242, -242, -242, -242, 0, -242, 0, 0, 0, 0, 0, 0, 0, 0, -242, 0, 0, -242, -242, 0, -242, 0, -242, -242, 0, 0, 0, -242, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, -242, -242, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 641 - 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 642 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -143, -143, 0, -143, 0, -143, 0, -143, 0, 0, -143, -143, 0, -143, -143, 0, -143, 0, 0, 0, 0, 0, -143, -143, -143, 0, -143, -143, 0, -143, -143, -143, -143, -143, -143, 0, -143, 0, 0, -143, 0, 0, 0, 0, -143, 0, -143, -143, -143, 0, -143, 0, 0, 0, 0, 0, 0, 0, 0, -143, 0, 0, -143, -143, 0, -143, 0, -143, -143, 0, 0, 0, -143, -143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, -143, -143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 643 - -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, 0, -197, 0, -197, -197, -197, -197, -197, 0, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, -197, 0, 0, 0, -197, -197, -197, -197, -197, -197, 0, -197, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, 0, -197, -197, 0, -197, 0, -197, -197, 0, 0, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -500, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 644 - 0, 0, 0, 0, 0, 0, 0, -66, 0, 0, 0, 0, 0, 0, -66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 0, -202, 0, -202, -202, -202, -202, -202, 0, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 0, 0, 0, -202, -202, -202, -202, -202, -202, 0, -202, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, -202, -202, 0, -202, 0, -202, -202, 0, 0, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 645 - -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, 0, -191, 0, -191, -191, -191, -191, -191, 0, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, -191, 0, 0, 0, -191, -191, -191, -191, -191, -191, 0, -191, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, 0, -191, -191, 0, -191, 0, -191, -191, 0, 0, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 646 - 0, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, -500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 647 - 0, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, 0, -199, 0, -199, -199, -199, -199, -199, 0, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, -199, 0, 0, 0, -199, -199, -199, -199, -199, -199, 0, -199, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, 0, -199, -199, 0, -199, 0, -199, -199, 0, 0, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 648 - -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 0, -188, 0, -188, -188, -188, -188, -188, 0, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 0, 0, 0, -188, -188, -188, -188, -188, -188, 0, -188, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, 0, -188, -188, 0, -188, 0, -188, -188, 0, 0, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -63, 0, 0, 0, 0, 0, 0, -63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 649 - -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, 0, -201, 0, -201, -201, -201, -201, -201, 0, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, -201, 0, 0, 0, -201, -201, -201, -201, -201, -201, 0, -201, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, 0, -201, -201, 0, -201, 0, -201, -201, 0, 0, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, 0, -193, 0, -193, -193, -193, -193, -193, 0, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, 0, 0, 0, -193, -193, -193, -193, -193, -193, 0, -193, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, 0, -193, -193, 0, -193, 0, -193, -193, 0, 0, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 650 - -916, 0, 0, 0, 0, 0, 0, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -916, 0, 0, 0, 0, -916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -504, 0, 0, 0, 0, 0, 0, -504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 651 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 652 - -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, 0, -187, 0, -187, -187, -187, -187, -187, 0, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, -187, 0, 0, 0, -187, -187, -187, -187, -187, -187, 0, -187, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, 0, -187, -187, 0, -187, 0, -187, -187, 0, 0, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, 0, -190, 0, -190, -190, -190, -190, -190, 0, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, 0, 0, 0, -190, -190, -190, -190, -190, -190, 0, -190, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, 0, -190, -190, 0, -190, 0, -190, -190, 0, 0, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 653 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, 0, 0, 0, 0, 0, 0, 0, 0, 0, -690, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, 0, -203, 0, -203, -203, -203, -203, -203, 0, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, -203, 0, 0, 0, -203, -203, -203, -203, -203, -203, 0, -203, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, 0, -203, -203, 0, -203, 0, -203, -203, 0, 0, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 654 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -528, 0, 0, 0, 0, 0, 0, 0, 0, 0, -528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -921, 0, 0, 0, 0, 0, 0, -921, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -921, 0, 0, 0, 0, -921, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 655 - -451, 0, 0, -451, 0, -451, 0, -451, 0, 0, -451, -451, 0, -451, -451, 0, -451, 0, 0, 0, 0, 0, -451, -451, -451, 0, -451, 0, 0, -451, 0, -451, 0, 0, 0, 0, -451, 0, -451, 0, 0, 0, 0, -451, 0, -451, 0, -451, 0, -451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -451, -451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -451, -451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 656 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -548, 0, 0, 0, 0, 0, 0, 0, 0, 0, -548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, 0, -189, 0, -189, -189, -189, -189, -189, 0, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, -189, 0, 0, 0, -189, -189, -189, -189, -189, -189, 0, -189, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, 0, -189, -189, 0, -189, 0, -189, -189, 0, 0, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 657 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -707, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 724, 0, 0, 0, 0, 0, 0, 0, 0, 0, -694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 658 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 724, 0, 0, 0, 0, 0, 0, 0, 0, 0, -702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 659 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -24, 0, 0, 0, 0, 0, 0, 0, 0, 0, -24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -456, 0, 0, -456, 0, -456, 0, -456, 0, 0, -456, -456, 0, -456, -456, 0, -456, 0, 0, 0, 0, 0, -456, -456, -456, 0, -456, 0, 0, -456, 0, -456, 0, 0, 0, 0, -456, 0, 0, -456, 0, 0, 0, 0, -456, 0, -456, 0, -456, 0, -456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456, -456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456, -456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 660 - -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, 0, -204, 0, -204, -204, -204, -204, -204, 0, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, -204, 0, 0, 0, -204, -204, -204, -204, -204, -204, 0, -204, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, 0, -204, -204, 0, -204, 0, -204, -204, 0, 0, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -552, 0, 0, 0, 0, 0, 0, 0, 0, 0, -552, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 661 - -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, 0, -206, 0, -206, -206, -206, -206, -206, 0, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, 0, 0, 0, -206, -206, -206, -206, -206, -206, 0, -206, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, 0, -206, -206, 0, -206, 0, -206, -206, 0, 0, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, -711, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 662 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, -706, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 663 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -21, 0, 0, 0, 0, 0, 0, 0, 0, 0, -21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 664 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, 0, -206, 0, -206, -206, -206, -206, -206, 0, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, 0, 0, 0, -206, -206, -206, -206, -206, -206, 0, -206, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, 0, -206, -206, 0, -206, 0, -206, -206, 0, 0, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 665 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, 0, -208, 0, -208, -208, -208, -208, -208, 0, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, -208, 0, 0, 0, -208, -208, -208, -208, -208, -208, 0, -208, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, 0, -208, -208, 0, -208, 0, -208, -208, 0, 0, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 666 - -749, 0, 0, 0, 0, 0, -749, 0, -749, 0, 0, 0, -749, 0, 0, -749, 0, 0, 0, -749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -749, 0, -749, -749, -749, -749, 0, 0, 0, 0, 0, -749, -749, -749, -749, 0, -749, -749, -749, -749, 0, 0, 0, 0, -749, -749, -749, -749, -749, 0, 0, -749, -749, -749, -749, 0, -749, -749, -749, -749, -749, -749, -749, -749, -749, 0, 0, 0, -749, 0, 0, 0, 0, -749, -749, -749, -749, -749, -749, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 667 - 725, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 668 - -179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -179, 0, 0, 0, 0, -179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 669 - -843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -843, 0, 0, 0, 0, -843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 670 - -377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -753, 0, 0, 0, 0, 0, -753, 0, -753, 0, 0, 0, -753, 0, 0, -753, 0, 0, 0, -753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -753, 0, -753, -753, -753, -753, 0, 0, 0, 0, 0, -753, -753, -753, -753, 0, -753, -753, -753, -753, 0, 0, 0, 0, -753, -753, -753, -753, -753, 0, 0, -753, -753, -753, -753, 0, -753, -753, -753, -753, -753, -753, -753, -753, -753, 0, 0, 0, -753, 0, 0, 0, 0, -753, -753, -753, -753, -753, -753, // State 671 - -844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -844, 0, 0, 0, 0, -844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 731, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, // State 672 - -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -175, 0, 0, 0, 0, -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 673 - -174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -174, 0, 0, 0, 0, -174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -181, 0, 0, 0, 0, -181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 674 - -453, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453, 0, 0, 0, 0, -453, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -848, 0, 0, 0, 0, -848, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 675 - -746, 0, 0, 0, 0, 0, -746, 0, -746, 0, 0, 0, -746, 0, 0, -746, 0, 0, 0, -746, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -746, 0, -746, -746, -746, -746, 0, 0, 0, 0, 0, -746, -746, -746, -746, 0, -746, -746, -746, -746, 0, 0, 0, 0, -746, -746, -746, -746, -746, 0, 0, -746, -746, -746, -746, 0, -746, -746, -746, -746, -746, -746, -746, -746, -746, 0, 0, 0, -746, 0, 0, 0, 0, -746, -746, -746, -746, -746, -746, + -379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 676 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, -337, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -849, 0, 0, 0, 0, -849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 677 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -177, 0, 0, 0, 0, -177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 678 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -176, 0, 0, 0, 0, -176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 679 - 0, 0, 0, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -449, 0, 0, 0, 0, -449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 680 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -750, 0, 0, 0, 0, 0, -750, 0, -750, 0, 0, 0, -750, 0, 0, -750, 0, 0, 0, -750, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -750, 0, -750, -750, -750, -750, 0, 0, 0, 0, 0, -750, -750, -750, -750, 0, -750, -750, -750, -750, 0, 0, 0, 0, -750, -750, -750, -750, -750, 0, 0, -750, -750, -750, -750, 0, -750, -750, -750, -750, -750, -750, -750, -750, -750, 0, 0, 0, -750, 0, 0, 0, 0, -750, -750, -750, -750, -750, -750, // State 681 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -339, 0, 0, 0, -339, 0, -339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 682 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -441, -441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -441, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 683 - -351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -351, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, -351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 684 - 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 685 - 759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 686 - 762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 687 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -443, -443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -443, 0, // State 688 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 689 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, 0, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, 0, 0, 0, 0, 0, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 690 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, -161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 691 - 0, -380, -380, 0, -380, 0, 0, 0, -380, 0, 0, 0, -380, 0, -380, -380, 0, 0, 0, 0, -380, -380, 0, 0, -382, 0, 0, -380, -380, 0, -380, 0, -380, -380, -380, -380, 0, -380, 0, 0, 0, 0, 0, 0, -380, 0, -380, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -380, 0, -380, -380, 0, 0, 0, -380, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 692 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, -906, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 0, 0, // State 693 - 0, 0, 0, 0, 0, 0, 0, 784, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 694 - 0, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, -531, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -545, 0, 0, 0, 0, 0, 0, 0, 0, 0, -547, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -545, 0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 695 - 0, 0, 0, 0, 0, 0, 0, 787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, -161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 513, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, -159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 696 - 0, -198, -198, 0, -198, 0, -198, 0, -198, -198, 0, 0, -198, 0, -198, -198, 0, 0, -198, 0, -198, -198, 0, 0, -225, 0, 0, -198, -198, 0, -198, 0, -198, -198, -198, -198, 0, -198, 0, 0, 0, 0, -198, 0, -198, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, -198, -198, 0, 0, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -241, -241, 0, -241, 0, -241, 0, -241, -241, 0, 0, -241, 0, -241, -241, 0, 0, -241, 0, -241, -241, 0, 0, -245, 0, 0, -241, -241, 0, -241, 0, -241, -241, -241, -241, 0, 0, -241, 0, 0, 0, 0, -241, 0, -241, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, -241, -241, 0, 0, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 697 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -382, -382, 0, -382, 0, 0, 0, -382, 0, 0, 0, -382, 0, -382, -382, 0, 0, 0, 0, -382, -382, 0, 0, -384, 0, 0, -382, -382, 0, -382, 0, -382, -382, -382, -382, 0, 0, -382, 0, 0, 0, 0, 0, 0, -382, 0, -382, -382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -382, 0, -382, -382, 0, 0, 0, -382, -382, 0, 0, 0, 0, 0, 0, 0, 0, 0, -382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 698 - 0, -186, -186, 0, -186, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -186, 0, -186, -186, 0, 0, -215, 0, 0, -186, -186, 0, -186, 0, -186, -186, -186, -186, 0, -186, 0, 0, 0, 0, -186, 0, -186, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, -186, -186, 0, 0, 0, -186, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, -911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 699 - 0, -246, -246, 0, -246, 0, 22, 0, -246, -246, 0, 0, -246, 0, -246, -246, 0, 0, 23, 0, -246, -246, 0, 0, -248, 0, 0, -246, -246, 0, -246, 0, -246, -246, -246, -246, 0, -246, 0, 0, 0, 0, 24, 0, -246, 0, -246, -246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -246, 0, -246, -246, 0, 0, 0, -246, -246, 0, 0, 0, 0, 0, 0, 0, 0, 0, -246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 789, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 700 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, -535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 701 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 702 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -200, -200, 0, -200, 0, -200, 0, -200, -200, 0, 0, -200, 0, -200, -200, 0, 0, -200, 0, -200, -200, 0, 0, -227, 0, 0, -200, -200, 0, -200, 0, -200, -200, -200, -200, 0, 0, -200, 0, 0, 0, 0, -200, 0, -200, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, -200, -200, 0, 0, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 703 - 0, -203, -203, 0, -203, 0, -203, 0, -203, -203, 0, 0, -203, 0, -203, -203, 0, 0, -203, 0, -203, -203, 0, 0, -230, 0, 0, -203, -203, 0, -203, 0, -203, -203, -203, -203, 0, -203, 0, 0, 0, 0, -203, 0, -203, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, -203, -203, 0, 0, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 704 - 0, 0, 0, 0, 0, 0, -117, -117, -117, -117, 0, 0, -117, 0, 0, -117, 0, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, -117, -117, -117, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, 0, -117, 0, 0, 0, 0, -117, -117, -117, 0, -117, -117, + 0, -188, -188, 0, -188, 0, -188, 0, -188, -188, 0, 0, -188, 0, -188, -188, 0, 0, -188, 0, -188, -188, 0, 0, -217, 0, 0, -188, -188, 0, -188, 0, -188, -188, -188, -188, 0, 0, -188, 0, 0, 0, 0, -188, 0, -188, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, -188, -188, 0, 0, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 705 - 0, 0, 0, 0, 0, 0, 0, -412, 0, 0, 0, 0, 0, 0, -412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, -509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, -507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 706 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -866, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -866, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 707 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 708 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -205, -205, 0, -205, 0, -205, 0, -205, -205, 0, 0, -205, 0, -205, -205, 0, 0, -205, 0, -205, -205, 0, 0, -232, 0, 0, -205, -205, 0, -205, 0, -205, -205, -205, -205, 0, 0, -205, 0, 0, 0, 0, -205, 0, -205, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, -205, -205, 0, 0, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 709 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, 0, -165, 0, -165, -165, -165, -165, -165, 0, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, 0, 0, 0, -165, -165, -165, -165, -165, -165, 0, -165, 0, 0, 0, 0, 0, 0, 0, 0, -165, 0, 0, -165, -165, 0, -165, 0, -165, -165, 0, 0, 0, -165, -165, 0, 0, 0, 0, 0, 0, 0, 0, 0, -165, -165, -165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 710 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -117, -117, -117, -117, 0, 0, -117, 0, 0, -117, 0, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, -117, -117, -117, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, -117, 0, 0, 0, -117, 0, 0, 0, 0, -117, -117, -117, 0, -117, -117, // State 711 - -832, 0, 0, -832, 0, -832, 0, -832, 0, 0, -832, -832, 0, -832, -832, 0, -832, 0, 0, 0, 0, 0, -832, -832, -832, 0, -832, 0, 0, -832, 0, -832, 0, 0, 0, 0, -832, 0, -832, 0, 0, 0, 0, -832, 0, -832, 0, -832, 0, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -832, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -832, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -414, 0, 0, 0, 0, 0, 0, -414, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 712 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 713 - 0, 0, 0, 0, 0, 0, 0, -67, 0, 0, 0, 0, 0, 0, -67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 714 - -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, 0, -193, 0, -193, -193, -193, -193, -193, 0, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, -193, 0, 0, 0, -193, -193, -193, -193, -193, -193, 0, -193, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, 0, -193, -193, 0, -193, 0, -193, -193, 0, 0, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -872, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -872, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 715 - 0, 0, 0, 0, 0, 0, 0, 796, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 716 - -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, 0, -194, 0, -194, -194, -194, -194, -194, 0, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, 0, 0, 0, -194, -194, -194, -194, -194, -194, 0, -194, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, 0, -194, -194, 0, -194, 0, -194, -194, 0, 0, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 717 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -687, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -837, 0, 0, -837, 0, -837, 0, -837, 0, 0, -837, -837, 0, -837, -837, 0, -837, 0, 0, 0, 0, 0, -837, -837, -837, 0, -837, 0, 0, -837, 0, -837, 0, 0, 0, 0, -837, 0, 0, -837, 0, 0, 0, 0, -837, 0, -837, 0, -837, 0, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -837, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -837, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 718 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, -681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 719 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, -686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -64, 0, 0, 0, 0, 0, 0, -64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 720 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 801, 0, 0, 0, 0, 0, 0, 0, 0, 0, -704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, 0, -195, 0, -195, -195, -195, -195, -195, 0, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, 0, 0, 0, -195, -195, -195, -195, -195, -195, 0, -195, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, 0, -195, -195, 0, -195, 0, -195, -195, 0, 0, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 721 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 801, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 722 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 803, 0, 0, 0, 0, 0, 0, 0, 0, 0, -701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, 0, -196, 0, -196, -196, -196, -196, -196, 0, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, 0, 0, 0, -196, -196, -196, -196, -196, -196, 0, -196, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, 0, -196, -196, 0, -196, 0, -196, -196, 0, 0, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 723 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 724 - -747, 0, 0, 0, 0, 0, -747, 0, -747, 0, 0, 0, -747, 0, 0, -747, 0, 0, 0, -747, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -747, 0, -747, -747, -747, -747, 0, 0, 0, 0, 0, -747, -747, -747, -747, 0, -747, -747, -747, -747, 0, 0, 0, 0, -747, -747, -747, -747, -747, 0, 0, -747, -747, -747, -747, 0, -747, -747, -747, -747, -747, -747, -747, -747, -747, 0, 0, 0, -747, 0, 0, 0, 0, -747, -747, -747, -747, -747, -747, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, -685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 725 - 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, -690, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 726 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 806, 0, 0, 0, 0, 0, 0, 0, 0, 0, -708, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 727 - -378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -22, 0, 0, 0, 0, 0, 0, 0, 0, 0, -22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 728 - -172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 808, 0, 0, 0, 0, 0, 0, 0, 0, 0, -705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 729 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -698, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 730 - 0, 0, 0, 0, 0, 0, 0, 813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -751, 0, 0, 0, 0, 0, -751, 0, -751, 0, 0, 0, -751, 0, 0, -751, 0, 0, 0, -751, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -751, 0, -751, -751, -751, -751, 0, 0, 0, 0, 0, -751, -751, -751, -751, 0, -751, -751, -751, -751, 0, 0, 0, 0, -751, -751, -751, -751, -751, 0, 0, -751, -751, -751, -751, 0, -751, -751, -751, -751, -751, -751, -751, -751, -751, 0, 0, 0, -751, 0, 0, 0, 0, -751, -751, -751, -751, -751, -751, // State 731 - -269, 0, 0, 0, 0, 0, -269, 0, -269, 0, 0, 0, -269, 0, 0, -269, 0, 0, 0, -269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -269, 0, -269, -269, -269, -269, 0, 0, 0, 0, 0, -269, -269, -269, -269, 0, -269, -269, -269, -269, 0, 0, 0, 0, -269, -269, -269, -269, -269, 0, 0, -269, -269, -269, -269, 0, -269, -269, -269, -269, -269, -269, -269, -269, -269, 0, 0, 0, -269, -269, 0, 0, 0, -269, -269, -269, -269, -269, -269, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 732 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 733 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 734 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 735 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 736 - 0, 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 737 - 0, 0, 0, 0, 0, 0, 0, -632, 0, 0, 0, 0, 0, 0, 819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -271, 0, 0, 0, 0, 0, -271, 0, -271, 0, 0, 0, -271, 0, 0, -271, 0, 0, 0, -271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -271, 0, -271, -271, -271, -271, 0, 0, 0, 0, 0, -271, -271, -271, -271, 0, -271, -271, -271, -271, 0, 0, 0, 0, -271, -271, -271, -271, -271, 0, 0, -271, -271, -271, -271, 0, -271, -271, -271, -271, -271, -271, -271, -271, -271, 0, 0, 0, -271, -271, 0, 0, 0, -271, -271, -271, -271, -271, -271, // State 738 - 0, 0, 0, 0, 0, 0, 0, -606, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -879, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -879, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 739 - 0, 0, 0, 0, 0, 0, 0, -525, 0, 0, 0, 0, 0, 0, -525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 740 - 0, 0, 0, 0, 0, 0, 0, 820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 741 - 0, 0, 0, 0, 0, 0, 0, -545, 0, 0, 0, 0, 0, 0, -545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 742 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -730, 0, 0, 0, 0, 0, 0, -730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 743 - -510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -636, 0, 0, 0, 0, 0, 0, 823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 744 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -610, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 745 - -518, 0, 0, 0, 0, 0, 0, -518, 0, 0, 0, 0, 0, 0, -518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -529, 0, 0, 0, 0, 0, 0, -529, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 746 - -446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 747 - -432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -549, 0, 0, 0, 0, 0, 0, -549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 748 - -435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -734, 0, 0, 0, 0, 0, 0, -734, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 749 - -77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -77, 0, 0, 0, -77, 0, 0, 0, 0, 0, 0, 0, -77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 750 - -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 751 - -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -522, 0, 0, 0, 0, 0, 0, -522, 0, 0, 0, 0, 0, 0, -522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 752 - -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 753 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 754 - 829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 755 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 0, + -74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -74, 0, 0, 0, -74, 0, 0, 0, 0, 0, 0, 0, -74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 756 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -869, 0, 0, 0, 0, 0, 0, 0, 0, 0, -869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 757 - 830, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 758 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, + -520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 759 - -752, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -752, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -873, 0, 0, 0, 0, 0, 0, 0, 0, 0, -873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 760 - 831, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 761 - -825, 0, 0, 0, 0, 0, -825, 0, -825, 0, 0, 0, -825, 0, 0, -825, 0, 0, 0, -825, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -825, 0, -825, -825, -825, -825, 0, 0, 0, 0, 0, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, -825, 0, 0, -825, -825, -825, -825, 0, -825, -825, -825, -825, -825, -825, -825, -825, -825, 0, 0, 0, -825, -825, 0, 0, 0, -825, -825, -825, -825, -825, -825, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, // State 762 - 833, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -874, 0, 0, 0, 0, 0, 0, 0, 0, 0, -874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 763 - -359, 0, 0, 0, 0, 0, -359, 0, -359, 0, 0, 0, -359, 0, 0, -359, 0, 0, 0, -359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -359, 0, -359, -359, -359, -359, 0, 0, 0, 0, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, -359, -359, -359, -359, 0, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, -359, -359, -359, -359, -359, 0, 0, 0, -359, -359, 0, 0, 0, -359, -359, -359, -359, -359, -359, + 834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 764 - -363, 0, 0, 0, 0, 0, -363, 0, -363, 0, 0, 0, -363, 0, 0, -363, 0, 0, 0, -363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -363, 0, -363, -363, -363, -363, 0, 0, 0, 0, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, -363, -363, -363, -363, 0, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, -363, -363, -363, -363, -363, 0, 0, 0, -363, -363, 0, 0, 0, -363, -363, -363, -363, -363, -363, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 0, 0, 0, 0, 0, 0, 0, 0, // State 765 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 766 - -872, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -872, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 767 - -889, 0, 0, 0, 0, 0, -889, 0, -889, 0, 0, 0, -889, 0, 0, -889, 0, 0, 0, -889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -889, 0, -889, -889, -889, -889, 0, 0, 0, 0, 0, -889, -889, -889, -889, 0, -889, -889, -889, -889, 0, 845, 0, 0, -889, -889, -889, -889, -889, 0, 0, -889, -889, -889, -889, 0, -889, -889, -889, -889, -889, -889, -889, -889, -889, 0, 0, 0, -889, -889, 0, 0, 0, -889, -889, -889, -889, -889, -889, + -830, 0, 0, 0, 0, 0, -830, 0, -830, 0, 0, 0, -830, 0, 0, -830, 0, 0, 0, -830, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -830, 0, -830, -830, -830, -830, 0, 0, 0, 0, 0, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, -830, 0, 0, -830, -830, -830, -830, 0, -830, -830, -830, -830, -830, -830, -830, -830, -830, 0, 0, 0, -830, -830, 0, 0, 0, -830, -830, -830, -830, -830, -830, // State 768 - 0, 0, 0, 0, 0, 0, 0, 846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 837, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, // State 769 - 0, -241, -241, 0, -241, 0, -241, 0, -241, -241, 0, 0, -241, 0, -241, -241, 0, 0, -241, 0, -241, -241, 0, 0, -245, 0, 0, -241, -241, 0, -241, 0, -241, -241, -241, -241, 0, -241, 0, 0, 0, 0, -241, 0, -241, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, -241, -241, 0, 0, 0, -241, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, -241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -361, 0, 0, 0, 0, 0, -361, 0, -361, 0, 0, 0, -361, 0, 0, -361, 0, 0, 0, -361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -361, 0, -361, -361, -361, -361, 0, 0, 0, 0, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, -361, -361, -361, -361, 0, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, -361, -361, -361, -361, -361, 0, 0, 0, -361, -361, 0, 0, 0, -361, -361, -361, -361, -361, -361, // State 770 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -365, 0, 0, 0, 0, 0, -365, 0, -365, 0, 0, 0, -365, 0, 0, -365, 0, 0, 0, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -365, 0, -365, -365, -365, -365, 0, 0, 0, 0, 0, -365, -365, -365, -365, 0, -365, -365, -365, -365, 0, -365, -365, -365, -365, -365, -365, -365, -365, 0, 0, -365, -365, -365, -365, 0, -365, -365, -365, -365, -365, -365, -365, -365, -365, 0, 0, 0, -365, -365, 0, 0, 0, -365, -365, -365, -365, -365, -365, // State 771 - 0, -740, -740, 0, -740, 0, 0, 0, -740, 0, 0, 0, -740, 0, -740, -740, 0, 0, 0, 0, -740, -740, 0, 0, -742, 0, 0, -740, -740, 0, -740, 0, -740, -740, -740, -740, 0, -740, 0, 0, 0, 0, 0, 0, -740, 0, -740, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -740, 0, -740, -740, 0, 0, 0, -740, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, -740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 772 - 0, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, -367, 0, 0, -365, 0, 0, -365, 0, -365, -365, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, -365, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -365, 0, -365, -365, 0, 0, 0, -365, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, -365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 773 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -894, 0, 0, 0, 0, 0, -894, 0, -894, 0, 0, 0, -894, 0, 0, -894, 0, 0, 0, -894, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -894, 0, -894, -894, -894, -894, 0, 0, 0, 0, 0, -894, -894, -894, -894, 0, -894, -894, -894, -894, 0, 849, 0, 0, -894, -894, -894, -894, -894, 0, 0, -894, -894, -894, -894, 0, -894, -894, -894, -894, -894, -894, -894, -894, -894, 0, 0, 0, -894, -894, 0, 0, 0, -894, -894, -894, -894, -894, -894, // State 774 - 0, -828, -828, 0, -828, 0, 0, 0, -828, 0, 0, 0, -828, 0, -828, -828, 0, 0, 0, 0, -828, -828, 0, 0, -830, 0, 0, -828, -828, 0, -828, 0, -828, -828, -828, -828, 0, -828, 0, 0, 0, 0, 0, 0, -828, 0, -828, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -828, 0, -828, -828, 0, 0, 0, -828, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -243, -243, 0, -243, 0, -243, 0, -243, -243, 0, 0, -243, 0, -243, -243, 0, 0, -243, 0, -243, -243, 0, 0, -247, 0, 0, -243, -243, 0, -243, 0, -243, -243, -243, -243, 0, 0, -243, 0, 0, 0, 0, -243, 0, -243, 0, -243, -243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -243, 0, -243, -243, 0, 0, 0, -243, -243, 0, 0, 0, 0, 0, 0, 0, 0, 0, -243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 775 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, 0, 0, 0, -894, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 776 - 0, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, 0, 0, 0, -890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -744, -744, 0, -744, 0, 0, 0, -744, 0, 0, 0, -744, 0, -744, -744, 0, 0, 0, 0, -744, -744, 0, 0, -746, 0, 0, -744, -744, 0, -744, 0, -744, -744, -744, -744, 0, 0, -744, 0, 0, 0, 0, 0, 0, -744, 0, -744, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -744, 0, -744, -744, 0, 0, 0, -744, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, -744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 777 - 0, 0, 0, 0, 0, 0, 0, -71, 0, 0, 0, 0, 0, 0, -71, 0, 0, 0, 0, 0, 0, 0, 0, 0, -71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, -369, 0, 0, -367, 0, 0, -367, 0, -367, -367, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, -367, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -367, 0, -367, -367, 0, 0, 0, -367, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, -367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 778 - -909, 0, 0, 0, 0, 0, -909, 0, -909, 0, 0, 0, -909, 0, 0, -909, 0, 0, 0, -909, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -909, 0, -909, -909, -909, -909, 0, 0, 0, 0, 0, -909, -909, -909, -909, 0, -909, -909, -909, -909, 0, 0, 0, 0, -909, -909, -909, -909, -909, 0, 0, -909, -909, -909, -909, 0, -909, -909, -909, -909, -909, -909, -909, -909, -909, 0, 0, 0, -909, -909, 0, 0, 0, -909, -909, -909, -909, -909, -909, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 779 - 0, -910, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, -912, 0, 0, -910, 0, 0, -910, 0, -910, -910, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, -910, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, -910, -910, 0, 0, 0, -910, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, -910, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -833, -833, 0, -833, 0, 0, 0, -833, 0, 0, 0, -833, 0, -833, -833, 0, 0, 0, 0, -833, -833, 0, 0, -835, 0, 0, -833, -833, 0, -833, 0, -833, -833, -833, -833, 0, 0, -833, 0, 0, 0, 0, 0, 0, -833, 0, -833, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, 0, -833, -833, 0, 0, 0, -833, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, -833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 780 - 0, 0, 0, 0, 0, 0, 0, 849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -899, 0, 0, 0, 0, 0, 0, -899, 0, 0, 0, 0, 0, 0, 0, 0, 0, -899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 781 - 0, 0, 0, 0, 0, 0, 0, 850, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -68, 0, 0, 0, 0, 0, 0, -68, 0, 0, 0, 0, 0, 0, 0, 0, 0, -68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 782 - 0, -195, -195, 0, -195, 0, -195, 0, -195, -195, 0, 0, -195, 0, -195, -195, 0, 0, -195, 0, -195, -195, 0, 0, -222, 0, 0, -195, -195, 0, -195, 0, -195, -195, -195, -195, 0, -195, 0, 0, 0, 0, -195, 0, -195, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, -195, -195, 0, 0, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -896, 0, 0, 0, 0, 0, 0, -896, 0, 0, 0, 0, 0, 0, 0, 0, 0, -896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 783 - 0, -189, -189, 0, -189, 0, -189, 0, -189, -189, 0, 0, -189, 0, -189, -189, 0, 0, -189, 0, -189, -189, 0, 0, -896, 0, 0, -189, -189, 0, -189, 0, -189, -189, -189, -189, 0, -189, 0, 0, 0, 0, -189, 0, -189, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, -189, -189, 0, 0, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -914, 0, 0, 0, 0, 0, -914, 0, -914, 0, 0, 0, -914, 0, 0, -914, 0, 0, 0, -914, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -914, 0, -914, -914, -914, -914, 0, 0, 0, 0, 0, -914, -914, -914, -914, 0, -914, -914, -914, -914, 0, 0, 0, 0, -914, -914, -914, -914, -914, 0, 0, -914, -914, -914, -914, 0, -914, -914, -914, -914, -914, -914, -914, -914, -914, 0, 0, 0, -914, -914, 0, 0, 0, -914, -914, -914, -914, -914, -914, // State 784 - 0, 0, 0, 0, 0, 0, 0, 855, 0, 0, 0, 0, 0, 0, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -915, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, -917, 0, 0, -915, 0, 0, -915, 0, -915, -915, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -915, 0, -915, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -915, 0, -915, -915, 0, 0, 0, -915, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, -915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 785 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 852, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 786 - 0, -199, -199, 0, -199, 0, -199, 0, -199, -199, 0, 0, -199, 0, -199, -199, 0, 0, -199, 0, -199, -199, 0, 0, -226, 0, 0, -199, -199, 0, -199, 0, -199, -199, -199, -199, 0, -199, 0, 0, 0, 0, -199, 0, -199, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, -199, -199, 0, 0, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 853, 0, 0, 0, 0, 0, 0, 259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 787 - 0, 0, 0, 0, 0, 0, 0, 857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -197, -197, 0, -197, 0, -197, 0, -197, -197, 0, 0, -197, 0, -197, -197, 0, 0, -197, 0, -197, -197, 0, 0, -224, 0, 0, -197, -197, 0, -197, 0, -197, -197, -197, -197, 0, 0, -197, 0, 0, 0, 0, -197, 0, -197, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, -197, -197, 0, 0, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 788 - 0, -185, -185, 0, -185, 0, -185, 0, -185, -185, 0, 0, -185, 0, -185, -185, 0, 0, -185, 0, -185, -185, 0, 0, -214, 0, 0, -185, -185, 0, -185, 0, -185, -185, -185, -185, 0, -185, 0, 0, 0, 0, -185, 0, -185, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, -185, -185, 0, 0, 0, -185, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, -185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -191, -191, 0, -191, 0, -191, 0, -191, -191, 0, 0, -191, 0, -191, -191, 0, 0, -191, 0, -191, -191, 0, 0, -901, 0, 0, -191, -191, 0, -191, 0, -191, -191, -191, -191, 0, 0, -191, 0, 0, 0, 0, -191, 0, -191, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, -191, -191, 0, 0, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 789 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 858, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 857, 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 790 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -907, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 791 - 0, -202, -202, 0, -202, 0, -202, 0, -202, -202, 0, 0, -202, 0, -202, -202, 0, 0, -202, 0, -202, -202, 0, 0, -229, 0, 0, -202, -202, 0, -202, 0, -202, -202, -202, -202, 0, -202, 0, 0, 0, 0, -202, 0, -202, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, -202, -202, 0, 0, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -201, -201, 0, -201, 0, -201, 0, -201, -201, 0, 0, -201, 0, -201, -201, 0, 0, -201, 0, -201, -201, 0, 0, -228, 0, 0, -201, -201, 0, -201, 0, -201, -201, -201, -201, 0, 0, -201, 0, 0, 0, 0, -201, 0, -201, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, -201, -201, 0, 0, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 792 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 793 - 0, -205, -205, 0, -205, 0, -205, 0, -205, -205, 0, 0, -205, 0, -205, -205, 0, 0, -205, 0, -205, -205, 0, 0, -232, 0, 0, -205, -205, 0, -205, 0, -205, -205, -205, -205, 0, -205, 0, 0, 0, 0, -205, 0, -205, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, -205, -205, 0, 0, 0, -205, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -187, -187, 0, -187, 0, -187, 0, -187, -187, 0, 0, -187, 0, -187, -187, 0, 0, -187, 0, -187, -187, 0, 0, -216, 0, 0, -187, -187, 0, -187, 0, -187, -187, -187, -187, 0, 0, -187, 0, 0, 0, 0, -187, 0, -187, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, -187, -187, 0, 0, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 794 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 795 - -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, 0, -196, 0, -196, -196, -196, -196, -196, 0, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, 0, 0, 0, -196, -196, -196, -196, -196, -196, 0, -196, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, 0, -196, -196, 0, -196, 0, -196, -196, 0, 0, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 796 - -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, 0, -190, 0, -190, -190, -190, -190, -190, 0, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, -190, 0, 0, 0, -190, -190, -190, -190, -190, -190, 0, -190, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, 0, -190, -190, 0, -190, 0, -190, -190, 0, 0, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -204, -204, 0, -204, 0, -204, 0, -204, -204, 0, 0, -204, 0, -204, -204, 0, 0, -204, 0, -204, -204, 0, 0, -231, 0, 0, -204, -204, 0, -204, 0, -204, -204, -204, -204, 0, 0, -204, 0, 0, 0, 0, -204, 0, -204, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, -204, -204, 0, 0, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 797 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, 0, 0, 0, 0, 0, 0, 0, 0, 0, -678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 798 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 865, 0, 0, 0, 0, 0, 0, 0, 0, 0, -663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -207, -207, 0, -207, 0, -207, 0, -207, -207, 0, 0, -207, 0, -207, -207, 0, 0, -207, 0, -207, -207, 0, 0, -234, 0, 0, -207, -207, 0, -207, 0, -207, -207, -207, -207, 0, 0, -207, 0, 0, 0, 0, -207, 0, -207, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, -207, -207, 0, 0, 0, -207, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, -207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 799 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 867, 0, 0, 0, 0, 0, 0, 0, 0, 0, -691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 800 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, 0, -198, 0, -198, -198, -198, -198, -198, 0, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, -198, 0, 0, 0, -198, -198, -198, -198, -198, -198, 0, -198, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, 0, -198, -198, 0, -198, 0, -198, -198, 0, 0, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 801 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 869, 0, 0, 0, 0, 0, 0, 0, 0, 0, -703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, 0, -192, 0, -192, -192, -192, -192, -192, 0, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, 0, 0, 0, -192, -192, -192, -192, -192, -192, 0, -192, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, 0, -192, -192, 0, -192, 0, -192, -192, 0, 0, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 802 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 0, 0, 0, 0, -682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 803 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 867, 0, 0, 0, 0, 0, 0, 0, 0, 0, -667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 804 - 0, 0, 0, 0, 0, 0, 0, 873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 869, 0, 0, 0, 0, 0, 0, 0, 0, 0, -695, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 805 - -271, 0, 0, 0, 0, 0, -271, 0, -271, 0, 0, 0, -271, 0, 0, -271, 0, 0, 0, -271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -271, 0, -271, -271, -271, -271, 0, 0, 0, 0, 0, -271, -271, -271, -271, 0, -271, -271, -271, -271, 0, 0, 0, 0, -271, -271, -271, -271, -271, 0, 0, -271, -271, -271, -271, 0, -271, -271, -271, -271, -271, -271, -271, -271, -271, 0, 0, 0, -271, -271, 0, 0, 0, -271, -271, -271, -271, -271, -271, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 806 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 269, 0, 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 871, 0, 0, 0, 0, 0, 0, 0, 0, 0, -707, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 807 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -697, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 808 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 809 - -908, 0, 0, 0, 0, 0, -908, 0, -908, 0, 0, 0, -908, 0, 0, -908, 0, 0, 0, -908, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -908, 0, -908, -908, -908, -908, 0, 0, 0, 0, 0, -908, -908, -908, -908, 0, -908, -908, -908, -908, 0, 0, 0, 0, -908, -908, -908, -908, -908, 0, 0, -908, -908, -908, -908, 0, -908, -908, -908, -908, -908, -908, -908, -908, -908, 0, 0, 0, -908, -908, 0, 0, 0, -908, -908, -908, -908, -908, -908, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 810 - 0, 0, 0, 0, 0, 0, 0, 878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -273, 0, 0, 0, 0, 0, -273, 0, -273, 0, 0, 0, -273, 0, 0, -273, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -273, 0, -273, -273, -273, -273, 0, 0, 0, 0, 0, -273, -273, -273, -273, 0, -273, -273, -273, -273, 0, 0, 0, 0, -273, -273, -273, -273, -273, 0, 0, -273, -273, -273, -273, 0, -273, -273, -273, -273, -273, -273, -273, -273, -273, 0, 0, 0, -273, -273, 0, 0, 0, -273, -273, -273, -273, -273, -273, // State 811 - -268, 0, 0, 0, 0, 0, -268, 0, -268, 0, 0, 0, -268, 0, 0, -268, 0, 0, 0, -268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -268, 0, -268, -268, -268, -268, 0, 0, 0, 0, 0, -268, -268, -268, -268, 0, -268, -268, -268, -268, 0, 0, 0, 0, -268, -268, -268, -268, -268, 0, 0, -268, -268, -268, -268, 0, -268, -268, -268, -268, -268, -268, -268, -268, -268, 0, 0, 0, -268, -268, 0, 0, 0, -268, -268, -268, -268, -268, -268, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 273, 0, 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 812 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 813 - 0, 0, 0, 0, 0, 0, -878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -878, 0, 0, 0, 0, 0, 0, -878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 814 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -913, 0, 0, 0, 0, 0, -913, 0, -913, 0, 0, 0, -913, 0, 0, -913, 0, 0, 0, -913, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -913, 0, -913, -913, -913, -913, 0, 0, 0, 0, 0, -913, -913, -913, -913, 0, -913, -913, -913, -913, 0, 0, 0, 0, -913, -913, -913, -913, -913, 0, 0, -913, -913, -913, -913, 0, -913, -913, -913, -913, -913, -913, -913, -913, -913, 0, 0, 0, -913, -913, 0, 0, 0, -913, -913, -913, -913, -913, -913, // State 815 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -267, 0, 0, 0, 0, 0, -267, 0, -267, 0, 0, 0, -267, 0, 0, -267, 0, 0, 0, -267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -267, 0, -267, -267, -267, -267, 0, 0, 0, 0, 0, -267, -267, -267, -267, 0, -267, -267, -267, -267, 0, 0, 0, 0, -267, -267, -267, -267, -267, 0, 0, -267, -267, -267, -267, 0, -267, -267, -267, -267, -267, -267, -267, -267, -267, 0, 0, 0, -267, -267, 0, 0, 0, -267, -267, -267, -267, -267, -267, // State 816 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -270, 0, 0, 0, 0, 0, -270, 0, -270, 0, 0, 0, -270, 0, 0, -270, 0, 0, 0, -270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -270, 0, -270, -270, -270, -270, 0, 0, 0, 0, 0, -270, -270, -270, -270, 0, -270, -270, -270, -270, 0, 0, 0, 0, -270, -270, -270, -270, -270, 0, 0, -270, -270, -270, -270, 0, -270, -270, -270, -270, -270, -270, -270, -270, -270, 0, 0, 0, -270, -270, 0, 0, 0, -270, -270, -270, -270, -270, -270, // State 817 - -407, 0, 0, 0, 0, 0, -407, 0, -407, 0, 0, 0, -407, 0, 0, -407, 0, 0, 0, -407, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -407, 0, -407, -407, -407, -407, 0, 0, 0, 0, 0, -407, -407, -407, -407, 0, -407, -407, -407, -407, 0, 0, 0, 0, -407, -407, -407, -407, -407, 0, 0, -407, -407, -407, -407, 0, -407, -407, -407, -407, -407, -407, -407, -407, -407, 0, 0, 0, -407, -407, 0, 0, 0, -407, -407, -407, -407, -407, -407, + 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, 0, 0, 0, -883, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 818 - 0, 0, 0, 0, 0, 0, 0, -631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -880, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -880, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 819 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -729, 0, 0, 0, 0, 0, 0, -729, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 820 - 0, 0, 0, 0, 0, 0, 0, -630, 0, 0, 0, 0, 0, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 821 - 0, 0, 0, 0, 0, 0, 0, -794, 0, 0, 0, 0, 0, 0, -794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -409, 0, 0, 0, 0, 0, -409, 0, -409, 0, 0, 0, -409, 0, 0, -409, 0, 0, 0, -409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -409, 0, -409, -409, -409, -409, 0, 0, 0, 0, 0, -409, -409, -409, -409, 0, -409, -409, -409, -409, 0, 0, 0, 0, -409, -409, -409, -409, -409, 0, 0, -409, -409, -409, -409, 0, -409, -409, -409, -409, -409, -409, -409, -409, -409, 0, 0, 0, -409, -409, 0, 0, 0, -409, -409, -409, -409, -409, -409, // State 822 - 0, 0, 0, 0, 0, 0, 0, -447, 0, 0, 0, 0, 0, 0, -447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -635, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 823 - 0, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 0, 0, 0, -353, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 824 - 0, 0, 0, 0, 0, 0, 0, 894, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -634, 0, 0, 0, 0, 0, 0, 281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 825 - -78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -78, 0, 0, 0, -78, 0, 0, 0, 0, 0, 0, 0, -78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -799, 0, 0, 0, 0, 0, 0, -799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 826 - -427, 0, 0, 0, 0, 0, -427, 0, -427, 0, 0, 0, -427, 0, 0, -427, 0, 0, 0, -427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -427, 0, -427, -427, -427, -427, 0, 0, 0, 0, 0, -427, -427, -427, -427, 0, -427, -427, -427, -427, 283, 895, 0, 0, -427, -427, -427, -427, -427, 0, 0, -427, -427, -427, -427, 0, -427, -427, -427, -427, -427, -427, -427, -427, -427, 0, 0, 0, -427, -427, 0, 0, 0, -427, -427, -427, -427, -427, -427, + 0, 0, 0, 0, 0, 0, 0, -452, 0, 0, 0, 0, 0, 0, -452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 827 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -355, 0, 0, 0, 0, 0, 0, -355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 828 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 285, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 895, 0, 0, 0, 0, 0, 0, 285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 829 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 0, + -75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -75, 0, 0, 0, -75, 0, 0, 0, 0, 0, 0, 0, -75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 830 - -826, 0, 0, 0, 0, 0, -826, 0, -826, 0, 0, 0, -826, 0, 0, -826, 0, 0, 0, -826, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -826, 0, -826, -826, -826, -826, 0, 0, 0, 0, 0, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, -826, 0, 0, -826, -826, -826, -826, 0, -826, -826, -826, -826, -826, -826, -826, -826, -826, 0, 0, 0, -826, -826, 0, 0, 0, -826, -826, -826, -826, -826, -826, + -429, 0, 0, 0, 0, 0, -429, 0, -429, 0, 0, 0, -429, 0, 0, -429, 0, 0, 0, -429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -429, 0, -429, -429, -429, -429, 0, 0, 0, 0, 0, -429, -429, -429, -429, 0, -429, -429, -429, -429, 286, 896, 0, 0, -429, -429, -429, -429, -429, 0, 0, -429, -429, -429, -429, 0, -429, -429, -429, -429, -429, -429, -429, -429, -429, 0, 0, 0, -429, -429, 0, 0, 0, -429, -429, -429, -429, -429, -429, // State 831 - 899, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 832 - -823, 0, 0, 0, 0, 0, -823, 0, -823, 0, 0, 0, -823, 0, 0, -823, 0, 0, 0, -823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -823, 0, -823, -823, -823, -823, 0, 0, 0, 0, 0, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, -823, 0, 0, -823, -823, -823, -823, 0, -823, -823, -823, -823, -823, -823, -823, -823, -823, 0, 0, 0, -823, -823, 0, 0, 0, -823, -823, -823, -823, -823, -823, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 0, // State 833 - -360, 0, 0, 0, 0, 0, -360, 0, -360, 0, 0, 0, -360, 0, 0, -360, 0, 0, 0, -360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -360, 0, -360, -360, -360, -360, 0, 0, 0, 0, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, -360, -360, -360, -360, 0, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, -360, -360, -360, -360, -360, 0, 0, 0, -360, -360, 0, 0, 0, -360, -360, -360, -360, -360, -360, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, // State 834 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -831, 0, 0, 0, 0, 0, -831, 0, -831, 0, 0, 0, -831, 0, 0, -831, 0, 0, 0, -831, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -831, 0, -831, -831, -831, -831, 0, 0, 0, 0, 0, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, -831, 0, 0, -831, -831, -831, -831, 0, -831, -831, -831, -831, -831, -831, -831, -831, -831, 0, 0, 0, -831, -831, 0, 0, 0, -831, -831, -831, -831, -831, -831, // State 835 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 900, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, // State 836 - -364, 0, 0, 0, 0, 0, -364, 0, -364, 0, 0, 0, -364, 0, 0, -364, 0, 0, 0, -364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -364, 0, -364, -364, -364, -364, 0, 0, 0, 0, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, -364, -364, -364, -364, 0, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, -364, -364, -364, -364, -364, 0, 0, 0, -364, -364, 0, 0, 0, -364, -364, -364, -364, -364, -364, + -828, 0, 0, 0, 0, 0, -828, 0, -828, 0, 0, 0, -828, 0, 0, -828, 0, 0, 0, -828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -828, 0, -828, -828, -828, -828, 0, 0, 0, 0, 0, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, -828, 0, 0, -828, -828, -828, -828, 0, -828, -828, -828, -828, -828, -828, -828, -828, -828, 0, 0, 0, -828, -828, 0, 0, 0, -828, -828, -828, -828, -828, -828, // State 837 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -362, 0, 0, 0, 0, 0, -362, 0, -362, 0, 0, 0, -362, 0, 0, -362, 0, 0, 0, -362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -362, 0, -362, -362, -362, -362, 0, 0, 0, 0, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, -362, -362, -362, -362, 0, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, -362, -362, -362, -362, -362, 0, 0, 0, -362, -362, 0, 0, 0, -362, -362, -362, -362, -362, -362, // State 838 - 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 839 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 840 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -366, 0, 0, 0, 0, 0, -366, 0, -366, 0, 0, 0, -366, 0, 0, -366, 0, 0, 0, -366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -366, 0, -366, -366, -366, -366, 0, 0, 0, 0, 0, -366, -366, -366, -366, 0, -366, -366, -366, -366, 0, -366, -366, -366, -366, -366, -366, -366, -366, 0, 0, -366, -366, -366, -366, 0, -366, -366, -366, -366, -366, -366, -366, -366, -366, 0, 0, 0, -366, -366, 0, 0, 0, -366, -366, -366, -366, -366, -366, // State 841 - 0, 0, 0, 0, 0, 0, -804, 0, -804, 0, 0, 0, -804, 0, 0, -804, 0, 0, 0, -804, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -804, 0, -804, -804, -804, -804, 0, 0, 0, 0, 0, -804, -804, -804, -804, 0, -804, -804, -804, -804, 0, 0, 0, 0, -804, -804, -804, -804, -804, 0, 0, -804, -804, -804, -804, 0, -804, -804, -804, -804, -804, -804, -804, -804, -804, 0, 0, 0, -804, -804, 0, 0, 0, -804, -804, -804, -804, -804, -804, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 842 - 904, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 843 - -871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 844 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 298, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 845 - 0, -239, -239, 0, -239, 0, -239, 0, -239, -239, 0, 0, -239, 0, -239, -239, 0, 0, -239, 0, -239, -239, 0, 0, -243, 0, 0, -239, -239, 0, -239, 0, -239, -239, -239, -239, 0, -239, 0, 0, 0, 0, -239, 0, -239, 0, -239, -239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -239, 0, -239, -239, 0, 0, 0, -239, -239, 0, 0, 0, 0, 0, 0, 0, 0, 0, -239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -809, 0, -809, 0, 0, 0, -809, 0, 0, -809, 0, 0, 0, -809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -809, 0, -809, -809, -809, -809, 0, 0, 0, 0, 0, -809, -809, -809, -809, 0, -809, -809, -809, -809, 0, 0, 0, 0, -809, -809, -809, -809, -809, 0, 0, -809, -809, -809, -809, 0, -809, -809, -809, -809, -809, -809, -809, -809, -809, 0, 0, 0, -809, -809, 0, 0, 0, -809, -809, -809, -809, -809, -809, // State 846 - 0, -240, -240, 0, -240, 0, -240, 0, -240, -240, 0, 0, -240, 0, -240, -240, 0, 0, -240, 0, -240, -240, 0, 0, -244, 0, 0, -240, -240, 0, -240, 0, -240, -240, -240, -240, 0, -240, 0, 0, 0, 0, -240, 0, -240, 0, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 0, -240, -240, 0, 0, 0, -240, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, -240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 906, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 847 - 0, 0, 0, 0, 0, 0, 0, -72, 0, 0, 0, 0, 0, 0, -72, 0, 0, 0, 0, 0, 0, 0, 0, 0, -72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 848 - 0, -200, -200, 0, -200, 0, -200, 0, -200, -200, 0, 0, -200, 0, -200, -200, 0, 0, -200, 0, -200, -200, 0, 0, -227, 0, 0, -200, -200, 0, -200, 0, -200, -200, -200, -200, 0, -200, 0, 0, 0, 0, -200, 0, -200, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, -200, -200, 0, 0, 0, -200, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, -200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 849 - 0, -197, -197, 0, -197, 0, -197, 0, -197, -197, 0, 0, -197, 0, -197, -197, 0, 0, -197, 0, -197, -197, 0, 0, -224, 0, 0, -197, -197, 0, -197, 0, -197, -197, -197, -197, 0, -197, 0, 0, 0, 0, -197, 0, -197, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, -197, -197, 0, 0, 0, -197, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, -197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -242, -242, 0, -242, 0, -242, 0, -242, -242, 0, 0, -242, 0, -242, -242, 0, 0, -242, 0, -242, -242, 0, 0, -246, 0, 0, -242, -242, 0, -242, 0, -242, -242, -242, -242, 0, 0, -242, 0, 0, 0, 0, -242, 0, -242, 0, -242, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -242, 0, -242, -242, 0, 0, 0, -242, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, -242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 850 - 0, -191, -191, 0, -191, 0, -191, 0, -191, -191, 0, 0, -191, 0, -191, -191, 0, 0, -191, 0, -191, -191, 0, 0, -218, 0, 0, -191, -191, 0, -191, 0, -191, -191, -191, -191, 0, -191, 0, 0, 0, 0, -191, 0, -191, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, -191, -191, 0, 0, 0, -191, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, -191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -69, 0, 0, 0, 0, 0, 0, -69, 0, 0, 0, 0, 0, 0, 0, 0, 0, -69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 851 - 0, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, -532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -202, -202, 0, -202, 0, -202, 0, -202, -202, 0, 0, -202, 0, -202, -202, 0, 0, -202, 0, -202, -202, 0, 0, -229, 0, 0, -202, -202, 0, -202, 0, -202, -202, -202, -202, 0, 0, -202, 0, 0, 0, 0, -202, 0, -202, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, -202, -202, 0, 0, 0, -202, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 852 - 0, -188, -188, 0, -188, 0, -188, 0, -188, -188, 0, 0, -188, 0, -188, -188, 0, 0, -188, 0, -188, -188, 0, 0, -895, 0, 0, -188, -188, 0, -188, 0, -188, -188, -188, -188, 0, -188, 0, 0, 0, 0, -188, 0, -188, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, -188, -188, 0, 0, 0, -188, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, -188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -199, -199, 0, -199, 0, -199, 0, -199, -199, 0, 0, -199, 0, -199, -199, 0, 0, -199, 0, -199, -199, 0, 0, -226, 0, 0, -199, -199, 0, -199, 0, -199, -199, -199, -199, 0, 0, -199, 0, 0, 0, 0, -199, 0, -199, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, -199, -199, 0, 0, 0, -199, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, -199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 853 - 0, 0, 0, 0, 0, 0, 0, -892, 0, 0, 0, 0, 0, 0, -892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -193, -193, 0, -193, 0, -193, 0, -193, -193, 0, 0, -193, 0, -193, -193, 0, 0, -193, 0, -193, -193, 0, 0, -220, 0, 0, -193, -193, 0, -193, 0, -193, -193, -193, -193, 0, 0, -193, 0, 0, 0, 0, -193, 0, -193, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, -193, -193, 0, 0, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 854 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -904, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, -536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 855 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -898, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -190, -190, 0, -190, 0, -190, 0, -190, -190, 0, 0, -190, 0, -190, -190, 0, 0, -190, 0, -190, -190, 0, 0, -900, 0, 0, -190, -190, 0, -190, 0, -190, -190, -190, -190, 0, 0, -190, 0, 0, 0, 0, -190, 0, -190, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, -190, -190, 0, 0, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 856 - 0, -201, -201, 0, -201, 0, -201, 0, -201, -201, 0, 0, -201, 0, -201, -201, 0, 0, -201, 0, -201, -201, 0, 0, -228, 0, 0, -201, -201, 0, -201, 0, -201, -201, -201, -201, 0, -201, 0, 0, 0, 0, -201, 0, -201, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, -201, -201, 0, 0, 0, -201, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, -201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -909, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 857 - 0, -187, -187, 0, -187, 0, -187, 0, -187, -187, 0, 0, -187, 0, -187, -187, 0, 0, -187, 0, -187, -187, 0, 0, -216, 0, 0, -187, -187, 0, -187, 0, -187, -187, -187, -187, 0, -187, 0, 0, 0, 0, -187, 0, -187, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, -187, -187, 0, 0, 0, -187, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 858 - 0, -204, -204, 0, -204, 0, -204, 0, -204, -204, 0, 0, -204, 0, -204, -204, 0, 0, -204, 0, -204, -204, 0, 0, -231, 0, 0, -204, -204, 0, -204, 0, -204, -204, -204, -204, 0, -204, 0, 0, 0, 0, -204, 0, -204, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, -204, -204, 0, 0, 0, -204, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, -204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -203, -203, 0, -203, 0, -203, 0, -203, -203, 0, 0, -203, 0, -203, -203, 0, 0, -203, 0, -203, -203, 0, 0, -230, 0, 0, -203, -203, 0, -203, 0, -203, -203, -203, -203, 0, 0, -203, 0, 0, 0, 0, -203, 0, -203, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, -203, -203, 0, 0, 0, -203, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, -203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 859 - 0, -206, -206, 0, -206, 0, -206, 0, -206, -206, 0, 0, -206, 0, -206, -206, 0, 0, -206, 0, -206, -206, 0, 0, -233, 0, 0, -206, -206, 0, -206, 0, -206, -206, -206, -206, 0, -206, 0, 0, 0, 0, -206, 0, -206, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, -206, -206, 0, 0, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -189, -189, 0, -189, 0, -189, 0, -189, -189, 0, 0, -189, 0, -189, -189, 0, 0, -189, 0, -189, -189, 0, 0, -218, 0, 0, -189, -189, 0, -189, 0, -189, -189, -189, -189, 0, 0, -189, 0, 0, 0, 0, -189, 0, -189, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, -189, -189, 0, 0, 0, -189, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, -189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 860 - 0, 0, 0, 0, 0, 0, 0, -329, 0, 0, 0, 0, 0, 0, -329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -329, 0, 0, 0, 0, 0, -329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -329, 0, 0, -329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -206, -206, 0, -206, 0, -206, 0, -206, -206, 0, 0, -206, 0, -206, -206, 0, 0, -206, 0, -206, -206, 0, 0, -233, 0, 0, -206, -206, 0, -206, 0, -206, -206, -206, -206, 0, 0, -206, 0, 0, 0, 0, -206, 0, -206, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, -206, -206, 0, 0, 0, -206, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, -206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 861 - -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, 0, -192, 0, -192, -192, -192, -192, -192, 0, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, -192, 0, 0, 0, -192, -192, -192, -192, -192, -192, 0, -192, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, 0, -192, -192, 0, -192, 0, -192, -192, 0, 0, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -208, -208, 0, -208, 0, -208, 0, -208, -208, 0, 0, -208, 0, -208, -208, 0, 0, -208, 0, -208, -208, 0, 0, -235, 0, 0, -208, -208, 0, -208, 0, -208, -208, -208, -208, 0, 0, -208, 0, 0, 0, 0, -208, 0, -208, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, -208, -208, 0, 0, 0, -208, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, -208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 862 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 920, 0, 0, 0, 0, 0, 0, 0, 0, 0, -669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -331, 0, 0, 0, 0, 0, 0, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -331, 0, 0, 0, 0, 0, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -331, 0, 0, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 863 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 922, 0, 0, 0, 0, 0, 0, 0, 0, 0, -660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, 0, -194, 0, -194, -194, -194, -194, -194, 0, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, -194, 0, 0, 0, -194, -194, -194, -194, -194, -194, 0, -194, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, 0, -194, -194, 0, -194, 0, -194, -194, 0, 0, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 864 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -636, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 920, 0, 0, 0, 0, 0, 0, 0, 0, 0, -673, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 865 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 923, 0, 0, 0, 0, 0, 0, 0, 0, 0, -692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 922, 0, 0, 0, 0, 0, 0, 0, 0, 0, -664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 866 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 867 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, -682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 923, 0, 0, 0, 0, 0, 0, 0, 0, 0, -696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 868 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -695, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 869 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, 0, 0, 0, 0, 0, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, -686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 870 - 0, 0, 0, 0, 0, 0, 0, 929, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 871 - -270, 0, 0, 0, 0, 0, -270, 0, -270, 0, 0, 0, -270, 0, 0, -270, 0, 0, 0, -270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -270, 0, -270, -270, -270, -270, 0, 0, 0, 0, 0, -270, -270, -270, -270, 0, -270, -270, -270, -270, 0, 0, 0, 0, -270, -270, -270, -270, -270, 0, 0, -270, -270, -270, -270, 0, -270, -270, -270, -270, -270, -270, -270, -270, -270, 0, 0, 0, -270, -270, 0, 0, 0, -270, -270, -270, -270, -270, -270, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 308, 0, 0, 0, 0, 0, 0, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 872 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -269, 0, 0, 0, 0, 0, -269, 0, -269, 0, 0, 0, -269, 0, 0, -269, 0, 0, 0, -269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -269, 0, -269, -269, -269, -269, 0, 0, 0, 0, 0, -269, -269, -269, -269, 0, -269, -269, -269, -269, 0, 0, 0, 0, -269, -269, -269, -269, -269, 0, 0, -269, -269, -269, -269, 0, -269, -269, -269, -269, -269, -269, -269, -269, -269, 0, 0, 0, -269, -269, 0, 0, 0, -269, -269, -269, -269, -269, -269, // State 873 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -272, 0, 0, 0, 0, 0, -272, 0, -272, 0, 0, 0, -272, 0, 0, -272, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -272, 0, -272, -272, -272, -272, 0, 0, 0, 0, 0, -272, -272, -272, -272, 0, -272, -272, -272, -272, 0, 0, 0, 0, -272, -272, -272, -272, -272, 0, 0, -272, -272, -272, -272, 0, -272, -272, -272, -272, -272, -272, -272, -272, -272, 0, 0, 0, -272, -272, 0, 0, 0, -272, -272, -272, -272, -272, -272, // State 874 - -409, 0, 0, 0, 0, 0, -409, 0, -409, 0, 0, 0, -409, 0, 0, -409, 0, 0, 0, -409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -409, 0, -409, -409, -409, -409, 0, 0, 0, 0, 0, -409, -409, -409, -409, 0, -409, -409, -409, -409, 0, 0, 0, 0, -409, -409, -409, -409, -409, 0, 0, -409, -409, -409, -409, 0, -409, -409, -409, -409, -409, -409, -409, -409, -409, 0, 0, 0, -409, -409, 0, 0, 0, -409, -409, -409, -409, -409, -409, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 875 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -411, 0, 0, 0, 0, 0, -411, 0, -411, 0, 0, 0, -411, 0, 0, -411, 0, 0, 0, -411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -411, 0, -411, -411, -411, -411, 0, 0, 0, 0, 0, -411, -411, -411, -411, 0, -411, -411, -411, -411, 0, 0, 0, 0, -411, -411, -411, -411, -411, 0, 0, -411, -411, -411, -411, 0, -411, -411, -411, -411, -411, -411, -411, -411, -411, 0, 0, 0, -411, -411, 0, 0, 0, -411, -411, -411, -411, -411, -411, // State 876 - -399, 0, 0, 0, 0, 0, -399, 0, -399, 0, 0, 0, -399, 0, 0, -399, 0, 0, 0, -399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -399, 0, -399, -399, -399, -399, 0, 0, 0, 0, 0, -399, -399, -399, -399, 0, -399, -399, -399, -399, 0, 0, 0, 0, -399, -399, -399, -399, -399, 0, 0, -399, -399, -399, -399, 0, -399, -399, -399, -399, -399, -399, -399, -399, -399, 0, 0, 0, -399, -399, 0, 0, 0, -399, -399, -399, -399, -399, -399, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 877 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -401, 0, 0, 0, 0, 0, -401, 0, -401, 0, 0, 0, -401, 0, 0, -401, 0, 0, 0, -401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -401, 0, -401, -401, -401, -401, 0, 0, 0, 0, 0, -401, -401, -401, -401, 0, -401, -401, -401, -401, 0, 0, 0, 0, -401, -401, -401, -401, -401, 0, 0, -401, -401, -401, -401, 0, -401, -401, -401, -401, -401, -401, -401, -401, -401, 0, 0, 0, -401, -401, 0, 0, 0, -401, -401, -401, -401, -401, -401, // State 878 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -266, 0, 0, 0, 0, 0, -266, 0, -266, 0, 0, 0, -266, 0, 0, -266, 0, 0, 0, -266, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -266, 0, -266, -266, -266, -266, 0, 0, 0, 0, 0, -266, -266, -266, -266, 0, -266, -266, -266, -266, 0, 0, 0, 0, -266, -266, -266, -266, -266, 0, 0, -266, -266, -266, -266, 0, -266, -266, -266, -266, -266, -266, -266, -266, -266, 0, 0, 0, -266, -266, 0, 0, 0, -266, -266, -266, -266, -266, -266, // State 879 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 880 - 0, 0, 0, 0, 0, 0, -877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -877, 0, 0, 0, 0, 0, 0, -877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 881 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, -882, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 882 - -406, 0, 0, 0, 0, 0, -406, 0, -406, 0, 0, 0, -406, 0, 0, -406, 0, 0, 0, -406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -406, 0, -406, -406, -406, -406, 0, 0, 0, 0, 0, -406, -406, -406, -406, 0, -406, -406, -406, -406, 0, 0, 0, 0, -406, -406, -406, -406, -406, 0, 0, -406, -406, -406, -406, 0, -406, -406, -406, -406, -406, -406, -406, -406, -406, 0, 0, 0, -406, -406, 0, 0, 0, -406, -406, -406, -406, -406, -406, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 312, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 883 - 0, 0, 0, 0, 0, 0, 0, -881, 0, 0, 0, 0, 0, 0, -881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -408, 0, 0, 0, 0, 0, -408, 0, -408, 0, 0, 0, -408, 0, 0, -408, 0, 0, 0, -408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -408, 0, -408, -408, -408, -408, 0, 0, 0, 0, 0, -408, -408, -408, -408, 0, -408, -408, -408, -408, 0, 0, 0, 0, -408, -408, -408, -408, -408, 0, 0, -408, -408, -408, -408, 0, -408, -408, -408, -408, -408, -408, -408, -408, -408, 0, 0, 0, -408, -408, 0, 0, 0, -408, -408, -408, -408, -408, -408, // State 884 - 0, 0, 0, 0, 0, 0, 0, -612, 0, 0, 0, 0, 0, 0, 937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 885 - 0, 0, 0, 0, 0, 0, 0, -526, 0, 0, 0, 0, 0, 0, -526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -616, 0, 0, 0, 0, 0, 0, 936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 886 - 0, 0, 0, 0, 0, 0, 0, -546, 0, 0, 0, 0, 0, 0, -546, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -530, 0, 0, 0, 0, 0, 0, -530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 887 - 0, 0, 0, 0, 0, 0, 0, -629, 0, 0, 0, 0, 0, 0, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -550, 0, 0, 0, 0, 0, 0, -550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 888 - 0, 0, 0, 0, 0, 0, 0, -624, 0, 0, 0, 0, 0, 0, 944, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -633, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 889 - 0, 0, 0, 0, 0, 0, 0, -19, 0, 0, 0, 0, 0, 0, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -628, 0, 0, 0, 0, 0, 0, 943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 890 - -393, 0, 0, 0, 0, 0, -393, 0, -393, 0, 0, 0, -393, 0, 0, -393, 0, 0, 0, -393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -393, 0, -393, -393, -393, -393, 0, 0, 0, 0, 0, -393, -393, -393, -393, 0, -393, -393, -393, -393, 0, 946, 0, 0, -393, -393, -393, -393, -393, 0, 0, -393, -393, -393, -393, 0, -393, -393, -393, -393, -393, -393, -393, -393, -393, 0, 0, 0, -393, -393, 0, 0, 0, -393, -393, -393, -393, -393, -393, + 0, 0, 0, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 891 - -517, 0, 0, 0, 0, 0, 0, -517, 0, 0, 0, 0, 0, 0, -517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -395, 0, 0, 0, 0, 0, -395, 0, -395, 0, 0, 0, -395, 0, 0, -395, 0, 0, 0, -395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -395, 0, -395, -395, -395, -395, 0, 0, 0, 0, 0, -395, -395, -395, -395, 0, -395, -395, -395, -395, 0, 945, 0, 0, -395, -395, -395, -395, -395, 0, 0, -395, -395, -395, -395, 0, -395, -395, -395, -395, -395, -395, -395, -395, -395, 0, 0, 0, -395, -395, 0, 0, 0, -395, -395, -395, -395, -395, -395, // State 892 - -520, 0, 0, 0, 0, 0, 0, -520, 0, 0, 0, 0, 0, 0, -520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -521, 0, 0, 0, 0, 0, 0, -521, 0, 0, 0, 0, 0, 0, -521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 893 - -434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -524, 0, 0, 0, 0, 0, 0, -524, 0, 0, 0, 0, 0, 0, -524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 894 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 895 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 896 - -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 897 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 898 - -824, 0, 0, 0, 0, 0, -824, 0, -824, 0, 0, 0, -824, 0, 0, -824, 0, 0, 0, -824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -824, 0, -824, -824, -824, -824, 0, 0, 0, 0, 0, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, -824, 0, 0, -824, -824, -824, -824, 0, -824, -824, -824, -824, -824, -824, -824, -824, -824, 0, 0, 0, -824, -824, 0, 0, 0, -824, -824, -824, -824, -824, -824, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -484, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 899 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -829, 0, 0, 0, 0, 0, -829, 0, -829, 0, 0, 0, -829, 0, 0, -829, 0, 0, 0, -829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -829, 0, -829, -829, -829, -829, 0, 0, 0, 0, 0, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, -829, 0, 0, -829, -829, -829, -829, 0, -829, -829, -829, -829, -829, -829, -829, -829, -829, 0, 0, 0, -829, -829, 0, 0, 0, -829, -829, -829, -829, -829, -829, // State 900 - -357, 0, 0, 0, 0, 0, -357, 0, -357, 0, 0, 0, -357, 0, 0, -357, 0, 0, 0, -357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -357, 0, -357, -357, -357, -357, 0, 0, 0, 0, 0, -357, -357, -357, -357, 0, -357, -357, -357, -357, 0, -357, -357, -357, -357, -357, -357, -357, -357, 0, 0, -357, -357, -357, -357, 0, -357, -357, -357, -357, -357, -357, -357, -357, -357, 0, 0, 0, -357, -357, 0, 0, 0, -357, -357, -357, -357, -357, -357, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 901 - -861, 0, 0, 0, 0, 0, -861, 0, -861, 0, 0, 0, -861, 0, 0, -861, 0, 0, 0, -861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -861, 0, -861, -861, -861, -861, 0, 0, 0, 0, 0, -861, -861, -861, -861, 0, -861, -861, -861, -861, 0, 0, 0, 0, -861, -861, -861, -861, -861, 0, 0, -861, -861, -861, -861, 0, -861, -861, -861, -861, -861, -861, -861, -861, -861, 0, 0, 0, -861, -861, 0, 0, 0, -861, -861, -861, -861, -861, -861, + -359, 0, 0, 0, 0, 0, -359, 0, -359, 0, 0, 0, -359, 0, 0, -359, 0, 0, 0, -359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -359, 0, -359, -359, -359, -359, 0, 0, 0, 0, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, -359, -359, -359, -359, 0, 0, -359, -359, -359, -359, 0, -359, -359, -359, -359, -359, -359, -359, -359, -359, 0, 0, 0, -359, -359, 0, 0, 0, -359, -359, -359, -359, -359, -359, // State 902 - 982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 983, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -866, 0, 0, 0, 0, 0, -866, 0, -866, 0, 0, 0, -866, 0, 0, -866, 0, 0, 0, -866, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -866, 0, -866, -866, -866, -866, 0, 0, 0, 0, 0, -866, -866, -866, -866, 0, -866, -866, -866, -866, 0, 0, 0, 0, -866, -866, -866, -866, -866, 0, 0, -866, -866, -866, -866, 0, -866, -866, -866, -866, -866, -866, -866, -866, -866, 0, 0, 0, -866, -866, 0, 0, 0, -866, -866, -866, -866, -866, -866, // State 903 - 0, 0, 0, 0, 0, 0, -802, 0, -802, 0, 0, 0, -802, 0, 0, -802, 0, 0, 0, -802, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -802, 0, -802, -802, -802, -802, 0, 0, 0, 0, 0, -802, -802, -802, -802, 0, -802, -802, -802, -802, 0, 0, 0, 0, -802, -802, -802, -802, -802, 0, 0, -802, -802, -802, -802, 0, -802, -802, -802, -802, -802, -802, -802, -802, -802, 0, 0, 0, -802, -802, 0, 0, 0, -802, -802, -802, -802, -802, -802, + 981, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 904 - 984, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, + 0, 0, 0, 0, 0, 0, -807, 0, -807, 0, 0, 0, -807, 0, 0, -807, 0, 0, 0, -807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -807, 0, -807, -807, -807, -807, 0, 0, 0, 0, 0, -807, -807, -807, -807, 0, -807, -807, -807, -807, 0, 0, 0, 0, -807, -807, -807, -807, -807, 0, 0, -807, -807, -807, -807, 0, -807, -807, -807, -807, -807, -807, -807, -807, -807, 0, 0, 0, -807, -807, 0, 0, 0, -807, -807, -807, -807, -807, -807, // State 905 - 0, 0, 0, 0, 0, 0, -805, 0, -805, 0, 0, 0, -805, 0, 0, -805, 0, 0, 0, -805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -805, 0, -805, -805, -805, -805, 0, 0, 0, 0, 0, -805, -805, -805, -805, 0, -805, -805, -805, -805, 0, 0, 0, 0, -805, -805, -805, -805, -805, 0, 0, -805, -805, -805, -805, 0, -805, -805, -805, -805, -805, -805, -805, -805, -805, 0, 0, 0, -805, -805, 0, 0, 0, -805, -805, -805, -805, -805, -805, + 983, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, // State 906 - 986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 987, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -810, 0, -810, 0, 0, 0, -810, 0, 0, -810, 0, 0, 0, -810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -810, 0, -810, -810, -810, -810, 0, 0, 0, 0, 0, -810, -810, -810, -810, 0, -810, -810, -810, -810, 0, 0, 0, 0, -810, -810, -810, -810, -810, 0, 0, -810, -810, -810, -810, 0, -810, -810, -810, -810, -810, -810, -810, -810, -810, 0, 0, 0, -810, -810, 0, 0, 0, -810, -810, -810, -810, -810, -810, // State 907 - -827, 0, 0, 0, 0, 0, -827, 0, -827, 0, 0, 0, -827, 0, 0, -827, 0, 0, 0, -827, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -827, 0, -827, -827, -827, -827, 0, 0, 0, 0, 0, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, -827, 0, 0, -827, -827, -827, -827, 0, -827, -827, -827, -827, -827, -827, -827, -827, -827, 0, 0, 0, -827, -827, 0, 0, 0, -827, -827, -827, -827, -827, -827, + 985, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 908 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -832, 0, 0, 0, 0, 0, -832, 0, -832, 0, 0, 0, -832, 0, 0, -832, 0, 0, 0, -832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -832, 0, -832, -832, -832, -832, 0, 0, 0, 0, 0, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, -832, 0, 0, -832, -832, -832, -832, 0, -832, -832, -832, -832, -832, -832, -832, -832, -832, 0, 0, 0, -832, -832, 0, 0, 0, -832, -832, -832, -832, -832, -832, // State 909 - 0, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, 0, 0, 0, -891, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, -842, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 910 - 0, -193, -193, 0, -193, 0, -193, 0, -193, -193, 0, 0, -193, 0, -193, -193, 0, 0, -193, 0, -193, -193, 0, 0, -220, 0, 0, -193, -193, 0, -193, 0, -193, -193, -193, -193, 0, -193, 0, 0, 0, 0, -193, 0, -193, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, -193, -193, 0, 0, 0, -193, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, -193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -195, -195, 0, -195, 0, -195, 0, -195, -195, 0, 0, -195, 0, -195, -195, 0, 0, -195, 0, -195, -195, 0, 0, -222, 0, 0, -195, -195, 0, -195, 0, -195, -195, -195, -195, 0, 0, -195, 0, 0, 0, 0, -195, 0, -195, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, -195, -195, 0, 0, 0, -195, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 911 - 0, 0, 0, 0, 0, 0, 0, 989, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 988, 0, 0, 0, 0, 0, 0, 331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 912 - 0, -194, -194, 0, -194, 0, -194, 0, -194, -194, 0, 0, -194, 0, -194, -194, 0, 0, -194, 0, -194, -194, 0, 0, -221, 0, 0, -194, -194, 0, -194, 0, -194, -194, -194, -194, 0, -194, 0, 0, 0, 0, -194, 0, -194, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, -194, -194, 0, 0, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -196, -196, 0, -196, 0, -196, 0, -196, -196, 0, 0, -196, 0, -196, -196, 0, 0, -196, 0, -196, -196, 0, 0, -223, 0, 0, -196, -196, 0, -196, 0, -196, -196, -196, -196, 0, 0, -196, 0, 0, 0, 0, -196, 0, -196, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, -196, -196, 0, 0, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 913 - 0, 0, 0, 0, 0, 0, 0, 991, 0, 0, 0, 0, 0, 0, 331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 990, 0, 0, 0, 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 914 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -901, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -906, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 915 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 916 - 0, 0, 0, 0, 0, 0, 0, -330, 0, 0, 0, 0, 0, 0, -330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -330, 0, 0, 0, 0, 0, -330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -330, 0, 0, -330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -332, 0, 0, 0, 0, 0, 0, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -332, 0, 0, 0, 0, 0, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -332, 0, 0, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 917 - 0, 0, 0, 0, 0, 0, 0, -326, 0, 0, 0, 0, 0, 0, -326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -326, 0, 0, 0, 0, 0, -326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -326, 0, 0, -326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -328, 0, 0, 0, 0, 0, 0, -328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -328, 0, 0, 0, 0, 0, -328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -328, 0, 0, -328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 918 - 0, 0, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -372, 0, 0, -372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 919 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 920 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 993, 0, 0, 0, 0, 0, 0, 0, 0, 0, -666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 992, 0, 0, 0, 0, 0, 0, 0, 0, 0, -670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 921 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 922 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -689, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 923 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, -683, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, -687, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 924 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, -679, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, -683, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 925 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 998, 0, 0, 0, 0, 0, 0, 0, 0, 0, -664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 997, 0, 0, 0, 0, 0, 0, 0, 0, 0, -668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 926 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 927 - -401, 0, 0, 0, 0, 0, -401, 0, -401, 0, 0, 0, -401, 0, 0, -401, 0, 0, 0, -401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -401, 0, -401, -401, -401, -401, 0, 0, 0, 0, 0, -401, -401, -401, -401, 0, -401, -401, -401, -401, 0, 0, 0, 0, -401, -401, -401, -401, -401, 0, 0, -401, -401, -401, -401, 0, -401, -401, -401, -401, -401, -401, -401, -401, -401, 0, 0, 0, -401, -401, 0, 0, 0, -401, -401, -401, -401, -401, -401, + -403, 0, 0, 0, 0, 0, -403, 0, -403, 0, 0, 0, -403, 0, 0, -403, 0, 0, 0, -403, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -403, 0, -403, -403, -403, -403, 0, 0, 0, 0, 0, -403, -403, -403, -403, 0, -403, -403, -403, -403, 0, 0, 0, 0, -403, -403, -403, -403, -403, 0, 0, -403, -403, -403, -403, 0, -403, -403, -403, -403, -403, -403, -403, -403, -403, 0, 0, 0, -403, -403, 0, 0, 0, -403, -403, -403, -403, -403, -403, // State 928 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -268, 0, 0, 0, 0, 0, -268, 0, -268, 0, 0, 0, -268, 0, 0, -268, 0, 0, 0, -268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -268, 0, -268, -268, -268, -268, 0, 0, 0, 0, 0, -268, -268, -268, -268, 0, -268, -268, -268, -268, 0, 0, 0, 0, -268, -268, -268, -268, -268, 0, 0, -268, -268, -268, -268, 0, -268, -268, -268, -268, -268, -268, -268, -268, -268, 0, 0, 0, -268, -268, 0, 0, 0, -268, -268, -268, -268, -268, -268, // State 929 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 930 - -408, 0, 0, 0, 0, 0, -408, 0, -408, 0, 0, 0, -408, 0, 0, -408, 0, 0, 0, -408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -408, 0, -408, -408, -408, -408, 0, 0, 0, 0, 0, -408, -408, -408, -408, 0, -408, -408, -408, -408, 0, 0, 0, 0, -408, -408, -408, -408, -408, 0, 0, -408, -408, -408, -408, 0, -408, -408, -408, -408, -408, -408, -408, -408, -408, 0, 0, 0, -408, -408, 0, 0, 0, -408, -408, -408, -408, -408, -408, + -410, 0, 0, 0, 0, 0, -410, 0, -410, 0, 0, 0, -410, 0, 0, -410, 0, 0, 0, -410, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -410, 0, -410, -410, -410, -410, 0, 0, 0, 0, 0, -410, -410, -410, -410, 0, -410, -410, -410, -410, 0, 0, 0, 0, -410, -410, -410, -410, -410, 0, 0, -410, -410, -410, -410, 0, -410, -410, -410, -410, -410, -410, -410, -410, -410, 0, 0, 0, -410, -410, 0, 0, 0, -410, -410, -410, -410, -410, -410, // State 931 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 932 - -398, 0, 0, 0, 0, 0, -398, 0, -398, 0, 0, 0, -398, 0, 0, -398, 0, 0, 0, -398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -398, 0, -398, -398, -398, -398, 0, 0, 0, 0, 0, -398, -398, -398, -398, 0, -398, -398, -398, -398, 0, 0, 0, 0, -398, -398, -398, -398, -398, 0, 0, -398, -398, -398, -398, 0, -398, -398, -398, -398, -398, -398, -398, -398, -398, 0, 0, 0, -398, -398, 0, 0, 0, -398, -398, -398, -398, -398, -398, + -400, 0, 0, 0, 0, 0, -400, 0, -400, 0, 0, 0, -400, 0, 0, -400, 0, 0, 0, -400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -400, 0, -400, -400, -400, -400, 0, 0, 0, 0, 0, -400, -400, -400, -400, 0, -400, -400, -400, -400, 0, 0, 0, 0, -400, -400, -400, -400, -400, 0, 0, -400, -400, -400, -400, 0, -400, -400, -400, -400, -400, -400, -400, -400, -400, 0, 0, 0, -400, -400, 0, 0, 0, -400, -400, -400, -400, -400, -400, // State 933 - -391, 0, 0, 0, 0, 0, -391, 0, -391, 0, 0, 0, -391, 0, 0, -391, 0, 0, 0, -391, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -391, 0, -391, -391, -391, -391, 0, 0, 0, 0, 0, -391, -391, -391, -391, 0, -391, -391, -391, -391, 0, 1004, 0, 0, -391, -391, -391, -391, -391, 0, 0, -391, -391, -391, -391, 0, -391, -391, -391, -391, -391, -391, -391, -391, -391, 0, 0, 0, -391, -391, 0, 0, 0, -391, -391, -391, -391, -391, -391, + -393, 0, 0, 0, 0, 0, -393, 0, -393, 0, 0, 0, -393, 0, 0, -393, 0, 0, 0, -393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -393, 0, -393, -393, -393, -393, 0, 0, 0, 0, 0, -393, -393, -393, -393, 0, -393, -393, -393, -393, 0, 1002, 0, 0, -393, -393, -393, -393, -393, 0, 0, -393, -393, -393, -393, 0, -393, -393, -393, -393, -393, -393, -393, -393, -393, 0, 0, 0, -393, -393, 0, 0, 0, -393, -393, -393, -393, -393, -393, // State 934 - -265, 0, 0, 0, 0, 0, -265, 0, -265, 0, 0, 0, -265, 0, 0, -265, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, -265, -265, -265, -265, 0, 0, 0, 0, 0, -265, -265, -265, -265, 0, -265, -265, -265, -265, 0, 0, 0, 0, -265, -265, -265, -265, -265, 0, 0, -265, -265, -265, -265, 0, -265, -265, -265, -265, -265, -265, -265, -265, -265, 0, 0, 0, -265, -265, 0, 0, 0, -265, -265, -265, -265, -265, -265, + -405, 0, 0, 0, 0, 0, -405, 0, -405, 0, 0, 0, -405, 0, 0, -405, 0, 0, 0, -405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -405, 0, -405, -405, -405, -405, 0, 0, 0, 0, 0, -405, -405, -405, -405, 0, -405, -405, -405, -405, 0, 0, 0, 0, -405, -405, -405, -405, -405, 0, 0, -405, -405, -405, -405, 0, -405, -405, -405, -405, -405, -405, -405, -405, -405, 0, 0, 0, -405, -405, 0, 0, 0, -405, -405, -405, -405, -405, -405, // State 935 - -403, 0, 0, 0, 0, 0, -403, 0, -403, 0, 0, 0, -403, 0, 0, -403, 0, 0, 0, -403, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -403, 0, -403, -403, -403, -403, 0, 0, 0, 0, 0, -403, -403, -403, -403, 0, -403, -403, -403, -403, 0, 0, 0, 0, -403, -403, -403, -403, -403, 0, 0, -403, -403, -403, -403, 0, -403, -403, -403, -403, -403, -403, -403, -403, -403, 0, 0, 0, -403, -403, 0, 0, 0, -403, -403, -403, -403, -403, -403, + 0, 0, 0, 0, 0, 0, 0, -613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 936 - 0, 0, 0, 0, 0, 0, 0, -609, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -607, 0, 0, 0, 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 937 - 0, 0, 0, 0, 0, 0, 0, -603, 0, 0, 0, 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -612, 0, 0, 0, 0, 0, 0, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 938 - 0, 0, 0, 0, 0, 0, 0, -608, 0, 0, 0, 0, 0, 0, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -630, 0, 0, 0, 0, 0, 0, 1007, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 939 - 0, 0, 0, 0, 0, 0, 0, -626, 0, 0, 0, 0, 0, 0, 1010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, 0, 0, 0, 0, -17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 940 - 0, 0, 0, 0, 0, 0, 0, -20, 0, 0, 0, 0, 0, 0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -798, 0, 0, 0, 0, 0, 0, -798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 941 - 0, 0, 0, 0, 0, 0, 0, -793, 0, 0, 0, 0, 0, 0, -793, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -627, 0, 0, 0, 0, 0, 0, 1009, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 942 - 0, 0, 0, 0, 0, 0, 0, -623, 0, 0, 0, 0, 0, 0, 1012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -620, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 943 - 0, 0, 0, 0, 0, 0, 0, -616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -354, 0, 0, 0, 0, 0, 0, -354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 944 - 0, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 0, 0, 0, -352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 945 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 946 - -433, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -433, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 947 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -426, 0, 0, 0, 0, 0, -426, 0, -426, 0, 0, 0, -426, 0, 0, -426, 0, 0, 0, -426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -426, 0, -426, -426, -426, -426, 0, 0, 0, 0, 0, -426, -426, -426, -426, 0, -426, -426, -426, -426, 0, 0, 0, 0, -426, -426, -426, -426, -426, 0, 0, -426, -426, -426, -426, 0, -426, -426, -426, -426, -426, -426, -426, -426, -426, 0, 0, 0, -426, -426, 0, 0, 0, -426, -426, -426, -426, -426, -426, // State 948 - -424, 0, 0, 0, 0, 0, -424, 0, -424, 0, 0, 0, -424, 0, 0, -424, 0, 0, 0, -424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -424, 0, -424, -424, -424, -424, 0, 0, 0, 0, 0, -424, -424, -424, -424, 0, -424, -424, -424, -424, 0, 0, 0, 0, -424, -424, -424, -424, -424, 0, 0, -424, -424, -424, -424, 0, -424, -424, -424, -424, -424, -424, -424, -424, -424, 0, 0, 0, -424, -424, 0, 0, 0, -424, -424, -424, -424, -424, -424, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -485, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 949 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -482, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -491, 0, 0, 0, 0, 0, -491, 0, -491, 0, 0, 0, -491, 0, 0, -491, 0, 0, 0, -491, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -491, 0, -491, -491, -491, -491, 0, 0, 0, 0, 0, -491, -491, -491, -491, 0, -491, -491, -491, -491, 0, 0, 0, 0, -491, -491, -491, -491, -491, 0, 0, -491, -491, -491, -491, 0, -491, -491, -491, -491, -491, -491, -491, -491, -491, 0, 0, 0, -491, -491, 0, 0, 0, -491, -491, -491, -491, -491, -491, // State 950 - -488, 0, 0, 0, 0, 0, -488, 0, -488, 0, 0, 0, -488, 0, 0, -488, 0, 0, 0, -488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -488, 0, -488, -488, -488, -488, 0, 0, 0, 0, 0, -488, -488, -488, -488, 0, -488, -488, -488, -488, 0, 0, 0, 0, -488, -488, -488, -488, -488, 0, 0, -488, -488, -488, -488, 0, -488, -488, -488, -488, -488, -488, -488, -488, -488, 0, 0, 0, -488, -488, 0, 0, 0, -488, -488, -488, -488, -488, -488, + 0, 0, 0, 0, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -467, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -467, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 424, // State 951 - 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + 0, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -466, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 952 - 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 953 - 0, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 954 - 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -294, 0, 0, 0, 0, 0, 0, -294, 0, 0, 0, 0, 0, 0, 0, 0, 0, -294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -294, 0, 0, 0, -294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -294, 0, -294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 955 - 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 345, 0, -543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 956 - 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 345, 0, -539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, -336, 0, -336, -336, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 957 - 0, 0, 0, 0, 0, 0, 0, -334, 0, 0, 0, 0, -334, 0, -334, -334, 0, 0, 0, 0, 0, 0, 0, 0, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -334, 0, 0, 0, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -334, 0, -334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, 0, -337, 0, -337, -337, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -337, 0, -337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 958 - 0, 0, 0, 0, 0, 0, 0, -335, 0, 0, 0, 0, -335, 0, -335, -335, 0, 0, 0, 0, 0, 0, 0, 0, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -335, 0, 0, 0, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -335, 0, -335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -488, -265, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, -488, 0, 0, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 959 - 0, 0, 0, 0, 0, 0, -485, -263, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, -485, 0, 0, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 960 - 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -293, 0, 0, 0, 0, 0, 0, -293, 0, 0, 0, 0, 0, 0, 0, 0, 0, -293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -293, 0, 0, 0, -293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -293, 0, -293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 961 - 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 962 - 0, 0, 0, 0, 0, 0, 347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 349, -892, 0, 0, 0, 0, 0, 0, -892, 0, 0, 0, 350, 0, 0, 0, 0, 0, -892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -892, 0, 0, 0, -892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -892, 0, -892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 963 - 0, 0, 0, 0, 0, 0, 349, -887, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, 350, 0, 0, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -887, 0, -887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 964 - 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, -743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 965 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, -739, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -739, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -292, 0, -292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 966 - 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -290, 0, -290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 967 - 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -288, 0, -288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 355, 0, -544, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 968 - 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 355, 0, -540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, -742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 969 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, -738, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -738, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -291, 0, -291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 970 - 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -289, 0, -289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -464, 0, -464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 971 - 0, 0, 0, 0, 0, 0, 0, -461, 0, 0, 0, 0, 0, 0, -461, 0, 0, 0, 0, 0, 0, 0, 0, 0, -461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -461, 0, 0, 0, -461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -461, 0, -461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -462, 0, -462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 972 - 0, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -459, 0, -459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -463, 0, -463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 973 - 0, 0, 0, 0, 0, 0, 0, -460, 0, 0, 0, 0, 0, 0, -460, 0, 0, 0, 0, 0, 0, 0, 0, 0, -460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -460, 0, 0, 0, -460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -460, 0, -460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -494, 0, 0, 0, 0, 0, -494, 0, -494, 0, 0, 0, -494, 0, 0, -494, 0, 0, 0, -494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -494, 0, -494, -494, -494, -494, 0, 0, 0, 0, 0, -494, -494, -494, -494, 0, -494, -494, -494, -494, 0, 0, 0, 0, -494, -494, -494, -494, -494, 0, 0, -494, -494, -494, -494, 0, -494, -494, -494, -494, -494, -494, -494, -494, -494, 0, 0, 0, -494, -494, 0, 0, 0, -494, -494, -494, -494, -494, -494, // State 974 - -491, 0, 0, 0, 0, 0, -491, 0, -491, 0, 0, 0, -491, 0, 0, -491, 0, 0, 0, -491, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -491, 0, -491, -491, -491, -491, 0, 0, 0, 0, 0, -491, -491, -491, -491, 0, -491, -491, -491, -491, 0, 0, 0, 0, -491, -491, -491, -491, -491, 0, 0, -491, -491, -491, -491, 0, -491, -491, -491, -491, -491, -491, -491, -491, -491, 0, 0, 0, -491, -491, 0, 0, 0, -491, -491, -491, -491, -491, -491, + -859, 0, 0, 0, 0, 0, -859, 0, -859, 0, 0, 0, -859, 0, 0, -859, 0, 0, 0, -859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -859, 0, -859, -859, -859, -859, 0, 0, 0, 0, 0, -859, -859, -859, -859, 0, -859, -859, -859, -859, 0, 0, 0, 1034, -859, -859, -859, -859, -859, 0, 0, -859, -859, -859, -859, 0, -859, -859, -859, -859, -859, -859, -859, -859, -859, 0, 0, 0, -859, -859, 0, 0, 0, -859, -859, -859, -859, -859, -859, // State 975 - -854, 0, 0, 0, 0, 0, -854, 0, -854, 0, 0, 0, -854, 0, 0, -854, 0, 0, 0, -854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -854, 0, -854, -854, -854, -854, 0, 0, 0, 0, 0, -854, -854, -854, -854, 0, -854, -854, -854, -854, 0, 0, 0, 1037, -854, -854, -854, -854, -854, 0, 0, -854, -854, -854, -854, 0, -854, -854, -854, -854, -854, -854, -854, -854, -854, 0, 0, 0, -854, -854, 0, 0, 0, -854, -854, -854, -854, -854, -854, + -860, 0, 0, 0, 0, 0, -860, 0, -860, 0, 0, 0, -860, 0, 0, -860, 0, 0, 0, -860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -860, 0, -860, -860, -860, -860, 0, 0, 0, 0, 0, -860, -860, -860, -860, 0, -860, -860, -860, -860, 0, 0, 0, 0, -860, -860, -860, -860, -860, 0, 0, -860, -860, -860, -860, 0, -860, -860, -860, -860, -860, -860, -860, -860, -860, 0, 0, 0, -860, -860, 0, 0, 0, -860, -860, -860, -860, -860, -860, // State 976 - -855, 0, 0, 0, 0, 0, -855, 0, -855, 0, 0, 0, -855, 0, 0, -855, 0, 0, 0, -855, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -855, 0, -855, -855, -855, -855, 0, 0, 0, 0, 0, -855, -855, -855, -855, 0, -855, -855, -855, -855, 0, 0, 0, 0, -855, -855, -855, -855, -855, 0, 0, -855, -855, -855, -855, 0, -855, -855, -855, -855, -855, -855, -855, -855, -855, 0, 0, 0, -855, -855, 0, 0, 0, -855, -855, -855, -855, -855, -855, + -863, 0, 0, 0, 0, 0, -863, 0, -863, 0, 0, 0, -863, 0, 0, -863, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -863, 0, -863, -863, -863, -863, 0, 0, 0, 0, 0, -863, -863, -863, -863, 0, -863, -863, -863, -863, 0, 0, 0, 1035, -863, -863, -863, -863, -863, 0, 0, -863, -863, -863, -863, 0, -863, -863, -863, -863, -863, -863, -863, -863, -863, 0, 0, 0, -863, -863, 0, 0, 0, -863, -863, -863, -863, -863, -863, // State 977 - -858, 0, 0, 0, 0, 0, -858, 0, -858, 0, 0, 0, -858, 0, 0, -858, 0, 0, 0, -858, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -858, 0, -858, -858, -858, -858, 0, 0, 0, 0, 0, -858, -858, -858, -858, 0, -858, -858, -858, -858, 0, 0, 0, 1038, -858, -858, -858, -858, -858, 0, 0, -858, -858, -858, -858, 0, -858, -858, -858, -858, -858, -858, -858, -858, -858, 0, 0, 0, -858, -858, 0, 0, 0, -858, -858, -858, -858, -858, -858, + -864, 0, 0, 0, 0, 0, -864, 0, -864, 0, 0, 0, -864, 0, 0, -864, 0, 0, 0, -864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -864, 0, -864, -864, -864, -864, 0, 0, 0, 0, 0, -864, -864, -864, -864, 0, -864, -864, -864, -864, 0, 0, 0, 0, -864, -864, -864, -864, -864, 0, 0, -864, -864, -864, -864, 0, -864, -864, -864, -864, -864, -864, -864, -864, -864, 0, 0, 0, -864, -864, 0, 0, 0, -864, -864, -864, -864, -864, -864, // State 978 - -859, 0, 0, 0, 0, 0, -859, 0, -859, 0, 0, 0, -859, 0, 0, -859, 0, 0, 0, -859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -859, 0, -859, -859, -859, -859, 0, 0, 0, 0, 0, -859, -859, -859, -859, 0, -859, -859, -859, -859, 0, 0, 0, 0, -859, -859, -859, -859, -859, 0, 0, -859, -859, -859, -859, 0, -859, -859, -859, -859, -859, -859, -859, -859, -859, 0, 0, 0, -859, -859, 0, 0, 0, -859, -859, -859, -859, -859, -859, + -358, 0, 0, 0, 0, 0, -358, 0, -358, 0, 0, 0, -358, 0, 0, -358, 0, 0, 0, -358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -358, 0, -358, -358, -358, -358, 0, 0, 0, 0, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, -358, -358, -358, -358, 0, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, -358, -358, -358, -358, -358, 0, 0, 0, -358, -358, 0, 0, 0, -358, -358, -358, -358, -358, -358, // State 979 - -356, 0, 0, 0, 0, 0, -356, 0, -356, 0, 0, 0, -356, 0, 0, -356, 0, 0, 0, -356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -356, 0, -356, -356, -356, -356, 0, 0, 0, 0, 0, -356, -356, -356, -356, 0, -356, -356, -356, -356, 0, -356, -356, -356, -356, -356, -356, -356, -356, 0, 0, -356, -356, -356, -356, 0, -356, -356, -356, -356, -356, -356, -356, -356, -356, 0, 0, 0, -356, -356, 0, 0, 0, -356, -356, -356, -356, -356, -356, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 980 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -808, 0, -808, 0, 0, 0, -808, 0, 0, -808, 0, 0, 0, -808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -808, 0, -808, -808, -808, -808, 0, 0, 0, 0, 0, -808, -808, -808, -808, 0, -808, -808, -808, -808, 0, 0, 0, 0, -808, -808, -808, -808, -808, 0, 0, -808, -808, -808, -808, 0, -808, -808, -808, -808, -808, -808, -808, -808, -808, 0, 0, 0, -808, -808, 0, 0, 0, -808, -808, -808, -808, -808, -808, // State 981 - 0, 0, 0, 0, 0, 0, -803, 0, -803, 0, 0, 0, -803, 0, 0, -803, 0, 0, 0, -803, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -803, 0, -803, -803, -803, -803, 0, 0, 0, 0, 0, -803, -803, -803, -803, 0, -803, -803, -803, -803, 0, 0, 0, 0, -803, -803, -803, -803, -803, 0, 0, -803, -803, -803, -803, 0, -803, -803, -803, -803, -803, -803, -803, -803, -803, 0, 0, 0, -803, -803, 0, 0, 0, -803, -803, -803, -803, -803, -803, + 1038, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, // State 982 - 1041, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, + 0, 0, 0, 0, 0, 0, -805, 0, -805, 0, 0, 0, -805, 0, 0, -805, 0, 0, 0, -805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -805, 0, -805, -805, -805, -805, 0, 0, 0, 0, 0, -805, -805, -805, -805, 0, -805, -805, -805, -805, 0, 0, 0, 0, -805, -805, -805, -805, -805, 0, 0, -805, -805, -805, -805, 0, -805, -805, -805, -805, -805, -805, -805, -805, -805, 0, 0, 0, -805, -805, 0, 0, 0, -805, -805, -805, -805, -805, -805, // State 983 - 0, 0, 0, 0, 0, 0, -800, 0, -800, 0, 0, 0, -800, 0, 0, -800, 0, 0, 0, -800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -800, 0, -800, -800, -800, -800, 0, 0, 0, 0, 0, -800, -800, -800, -800, 0, -800, -800, -800, -800, 0, 0, 0, 0, -800, -800, -800, -800, -800, 0, 0, -800, -800, -800, -800, 0, -800, -800, -800, -800, -800, -800, -800, -800, -800, 0, 0, 0, -800, -800, 0, 0, 0, -800, -800, -800, -800, -800, -800, + 1039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 984 - 1042, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1043, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -813, 0, -813, 0, 0, 0, -813, 0, 0, -813, 0, 0, 0, -813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -813, 0, -813, -813, -813, -813, 0, 0, 0, 0, 0, -813, -813, -813, -813, 0, -813, -813, -813, -813, 0, 0, 0, 0, -813, -813, -813, -813, -813, 0, 0, -813, -813, -813, -813, 0, -813, -813, -813, -813, -813, -813, -813, -813, -813, 0, 0, 0, -813, -813, 0, 0, 0, -813, -813, -813, -813, -813, -813, // State 985 - 0, 0, 0, 0, 0, 0, -808, 0, -808, 0, 0, 0, -808, 0, 0, -808, 0, 0, 0, -808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -808, 0, -808, -808, -808, -808, 0, 0, 0, 0, 0, -808, -808, -808, -808, 0, -808, -808, -808, -808, 0, 0, 0, 0, -808, -808, -808, -808, -808, 0, 0, -808, -808, -808, -808, 0, -808, -808, -808, -808, -808, -808, -808, -808, -808, 0, 0, 0, -808, -808, 0, 0, 0, -808, -808, -808, -808, -808, -808, + 1041, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, // State 986 - 1044, 0, 0, 0, 0, 0, -132, 0, -132, 0, 0, 0, -132, 0, 0, -132, 0, 0, 0, -132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -132, -132, -132, -132, 0, 0, 0, 0, 0, -132, 0, -132, -132, 0, 0, -132, 0, -132, 0, 0, 0, 0, 0, -132, -132, 0, -132, 0, 0, -132, 0, -132, -132, 0, -132, -132, -132, 0, -132, 0, 0, -132, -132, 0, 0, 0, -132, 0, 0, 0, 0, -132, -132, -132, -132, -132, -132, + -893, 0, 0, 0, 0, 0, -893, 0, -893, 0, 0, 0, -893, 0, 0, -893, 0, 0, 0, -893, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -893, 0, -893, -893, -893, -893, 0, 0, 0, 0, 0, -893, -893, -893, -893, 0, -893, -893, -893, -893, 0, 0, 0, 0, -893, -893, -893, -893, -893, 0, 0, -893, -893, -893, -893, 0, -893, -893, -893, -893, -893, -893, -893, -893, -893, 0, 0, 0, -893, -893, 0, 0, 0, -893, -893, -893, -893, -893, -893, // State 987 - -888, 0, 0, 0, 0, 0, -888, 0, -888, 0, 0, 0, -888, 0, 0, -888, 0, 0, 0, -888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -888, 0, -888, -888, -888, -888, 0, 0, 0, 0, 0, -888, -888, -888, -888, 0, -888, -888, -888, -888, 0, 0, 0, 0, -888, -888, -888, -888, -888, 0, 0, -888, -888, -888, -888, 0, -888, -888, -888, -888, -888, -888, -888, -888, -888, 0, 0, 0, -888, -888, 0, 0, 0, -888, -888, -888, -888, -888, -888, + 0, -198, -198, 0, -198, 0, -198, 0, -198, -198, 0, 0, -198, 0, -198, -198, 0, 0, -198, 0, -198, -198, 0, 0, -225, 0, 0, -198, -198, 0, -198, 0, -198, -198, -198, -198, 0, 0, -198, 0, 0, 0, 0, -198, 0, -198, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, -198, -198, 0, 0, 0, -198, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, -198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 988 - 0, -196, -196, 0, -196, 0, -196, 0, -196, -196, 0, 0, -196, 0, -196, -196, 0, 0, -196, 0, -196, -196, 0, 0, -223, 0, 0, -196, -196, 0, -196, 0, -196, -196, -196, -196, 0, -196, 0, 0, 0, 0, -196, 0, -196, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, -196, -196, 0, 0, 0, -196, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, -196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -192, -192, 0, -192, 0, -192, 0, -192, -192, 0, 0, -192, 0, -192, -192, 0, 0, -192, 0, -192, -192, 0, 0, -219, 0, 0, -192, -192, 0, -192, 0, -192, -192, -192, -192, 0, 0, -192, 0, 0, 0, 0, -192, 0, -192, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, -192, -192, 0, 0, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 989 - 0, -190, -190, 0, -190, 0, -190, 0, -190, -190, 0, 0, -190, 0, -190, -190, 0, 0, -190, 0, -190, -190, 0, 0, -217, 0, 0, -190, -190, 0, -190, 0, -190, -190, -190, -190, 0, -190, 0, 0, 0, 0, -190, 0, -190, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, -190, -190, 0, 0, 0, -190, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, -190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -908, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 990 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 991 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 992 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 362, 0, 0, 0, 0, 0, 0, 0, 0, 0, -684, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 993 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 362, 0, 0, 0, 0, 0, 0, 0, 0, 0, -680, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1046, 0, 0, 0, 0, 0, 0, 0, 0, 0, -669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 994 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1049, 0, 0, 0, 0, 0, 0, 0, 0, 0, -665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, -674, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 995 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1050, 0, 0, 0, 0, 0, 0, 0, 0, 0, -670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1049, 0, 0, 0, 0, 0, 0, 0, 0, 0, -665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 996 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1052, 0, 0, 0, 0, 0, 0, 0, 0, 0, -661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 997 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 998 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -402, 0, 0, 0, 0, 0, -402, 0, -402, 0, 0, 0, -402, 0, 0, -402, 0, 0, 0, -402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -402, 0, -402, -402, -402, -402, 0, 0, 0, 0, 0, -402, -402, -402, -402, 0, -402, -402, -402, -402, 0, 0, 0, 0, -402, -402, -402, -402, -402, 0, 0, -402, -402, -402, -402, 0, -402, -402, -402, -402, -402, -402, -402, -402, -402, 0, 0, 0, -402, -402, 0, 0, 0, -402, -402, -402, -402, -402, -402, // State 999 - -400, 0, 0, 0, 0, 0, -400, 0, -400, 0, 0, 0, -400, 0, 0, -400, 0, 0, 0, -400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -400, 0, -400, -400, -400, -400, 0, 0, 0, 0, 0, -400, -400, -400, -400, 0, -400, -400, -400, -400, 0, 0, 0, 0, -400, -400, -400, -400, -400, 0, 0, -400, -400, -400, -400, 0, -400, -400, -400, -400, -400, -400, -400, -400, -400, 0, 0, 0, -400, -400, 0, 0, 0, -400, -400, -400, -400, -400, -400, + -407, 0, 0, 0, 0, 0, -407, 0, -407, 0, 0, 0, -407, 0, 0, -407, 0, 0, 0, -407, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -407, 0, -407, -407, -407, -407, 0, 0, 0, 0, 0, -407, -407, -407, -407, 0, -407, -407, -407, -407, 0, 0, 0, 0, -407, -407, -407, -407, -407, 0, 0, -407, -407, -407, -407, 0, -407, -407, -407, -407, -407, -407, -407, -407, -407, 0, 0, 0, -407, -407, 0, 0, 0, -407, -407, -407, -407, -407, -407, // State 1000 - -267, 0, 0, 0, 0, 0, -267, 0, -267, 0, 0, 0, -267, 0, 0, -267, 0, 0, 0, -267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -267, 0, -267, -267, -267, -267, 0, 0, 0, 0, 0, -267, -267, -267, -267, 0, -267, -267, -267, -267, 0, 0, 0, 0, -267, -267, -267, -267, -267, 0, 0, -267, -267, -267, -267, 0, -267, -267, -267, -267, -267, -267, -267, -267, -267, 0, 0, 0, -267, -267, 0, 0, 0, -267, -267, -267, -267, -267, -267, + -397, 0, 0, 0, 0, 0, -397, 0, -397, 0, 0, 0, -397, 0, 0, -397, 0, 0, 0, -397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -397, 0, -397, -397, -397, -397, 0, 0, 0, 0, 0, -397, -397, -397, -397, 0, -397, -397, -397, -397, 0, 0, 0, 0, -397, -397, -397, -397, -397, 0, 0, -397, -397, -397, -397, 0, -397, -397, -397, -397, -397, -397, -397, -397, -397, 0, 0, 0, -397, -397, 0, 0, 0, -397, -397, -397, -397, -397, -397, // State 1001 - -405, 0, 0, 0, 0, 0, -405, 0, -405, 0, 0, 0, -405, 0, 0, -405, 0, 0, 0, -405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -405, 0, -405, -405, -405, -405, 0, 0, 0, 0, 0, -405, -405, -405, -405, 0, -405, -405, -405, -405, 0, 0, 0, 0, -405, -405, -405, -405, -405, 0, 0, -405, -405, -405, -405, 0, -405, -405, -405, -405, -405, -405, -405, -405, -405, 0, 0, 0, -405, -405, 0, 0, 0, -405, -405, -405, -405, -405, -405, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1002 - -395, 0, 0, 0, 0, 0, -395, 0, -395, 0, 0, 0, -395, 0, 0, -395, 0, 0, 0, -395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -395, 0, -395, -395, -395, -395, 0, 0, 0, 0, 0, -395, -395, -395, -395, 0, -395, -395, -395, -395, 0, 0, 0, 0, -395, -395, -395, -395, -395, 0, 0, -395, -395, -395, -395, 0, -395, -395, -395, -395, -395, -395, -395, -395, -395, 0, 0, 0, -395, -395, 0, 0, 0, -395, -395, -395, -395, -395, -395, + -404, 0, 0, 0, 0, 0, -404, 0, -404, 0, 0, 0, -404, 0, 0, -404, 0, 0, 0, -404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -404, 0, -404, -404, -404, -404, 0, 0, 0, 0, 0, -404, -404, -404, -404, 0, -404, -404, -404, -404, 0, 0, 0, 0, -404, -404, -404, -404, -404, 0, 0, -404, -404, -404, -404, 0, -404, -404, -404, -404, -404, -404, -404, -404, -404, 0, 0, 0, -404, -404, 0, 0, 0, -404, -404, -404, -404, -404, -404, // State 1003 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -604, 0, 0, 0, 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1004 - -264, 0, 0, 0, 0, 0, -264, 0, -264, 0, 0, 0, -264, 0, 0, -264, 0, 0, 0, -264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -264, 0, -264, -264, -264, -264, 0, 0, 0, 0, 0, -264, -264, -264, -264, 0, -264, -264, -264, -264, 0, 0, 0, 0, -264, -264, -264, -264, -264, 0, 0, -264, -264, -264, -264, 0, -264, -264, -264, -264, -264, -264, -264, -264, -264, 0, 0, 0, -264, -264, 0, 0, 0, -264, -264, -264, -264, -264, -264, + 0, 0, 0, 0, 0, 0, 0, -589, 0, 0, 0, 0, 0, 0, 1055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1005 - -402, 0, 0, 0, 0, 0, -402, 0, -402, 0, 0, 0, -402, 0, 0, -402, 0, 0, 0, -402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -402, 0, -402, -402, -402, -402, 0, 0, 0, 0, 0, -402, -402, -402, -402, 0, -402, -402, -402, -402, 0, 0, 0, 0, -402, -402, -402, -402, -402, 0, 0, -402, -402, -402, -402, 0, -402, -402, -402, -402, -402, -402, -402, -402, -402, 0, 0, 0, -402, -402, 0, 0, 0, -402, -402, -402, -402, -402, -402, + 0, 0, 0, 0, 0, 0, 0, -617, 0, 0, 0, 0, 0, 0, 1057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1006 - 0, 0, 0, 0, 0, 0, 0, -600, 0, 0, 0, 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -622, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1007 - 0, 0, 0, 0, 0, 0, 0, -585, 0, 0, 0, 0, 0, 0, 1059, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -629, 0, 0, 0, 0, 0, 0, 1059, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1008 - 0, 0, 0, 0, 0, 0, 0, -613, 0, 0, 0, 0, 0, 0, 1061, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -619, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1009 - 0, 0, 0, 0, 0, 0, 0, -618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -523, 0, 0, 0, 0, 0, 0, -523, 0, 0, 0, 0, 0, 0, -523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1010 - 0, 0, 0, 0, 0, 0, 0, -625, 0, 0, 0, 0, 0, 0, 1063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -428, 0, 0, 0, 0, 0, -428, 0, -428, 0, 0, 0, -428, 0, 0, -428, 0, 0, 0, -428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -428, 0, -428, -428, -428, -428, 0, 0, 0, 0, 0, -428, -428, -428, -428, 0, -428, -428, -428, -428, 0, 0, 0, 0, -428, -428, -428, -428, -428, 0, 0, -428, -428, -428, -428, 0, -428, -428, -428, -428, -428, -428, -428, -428, -428, 0, 0, 0, -428, -428, 0, 0, 0, -428, -428, -428, -428, -428, -428, // State 1011 - 0, 0, 0, 0, 0, 0, 0, -615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -105, 0, 0, 0, 0, 0, -105, 0, -105, 0, 0, 0, -105, 0, 0, -105, 0, 0, 0, -105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -105, 0, -105, -105, -105, -105, 0, 0, 0, 0, 0, -105, -105, -105, -105, 0, -105, -105, -105, -105, -105, -105, 0, 0, -105, -105, -105, -105, -105, 0, 0, -105, -105, -105, -105, 0, -105, -105, -105, -105, -105, -105, -105, -105, -105, 0, 0, 0, -105, -105, 0, 0, 0, -105, -105, -105, -105, -105, -105, // State 1012 - -519, 0, 0, 0, 0, 0, 0, -519, 0, 0, 0, 0, 0, 0, -519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -492, 0, 0, 0, 0, 0, -492, 0, -492, 0, 0, 0, -492, 0, 0, -492, 0, 0, 0, -492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -492, 0, -492, -492, -492, -492, 0, 0, 0, 0, 0, -492, -492, -492, -492, 0, -492, -492, -492, -492, 0, 0, 0, 0, -492, -492, -492, -492, -492, 0, 0, -492, -492, -492, -492, 0, -492, -492, -492, -492, -492, -492, -492, -492, -492, 0, 0, 0, -492, -492, 0, 0, 0, -492, -492, -492, -492, -492, -492, // State 1013 - -426, 0, 0, 0, 0, 0, -426, 0, -426, 0, 0, 0, -426, 0, 0, -426, 0, 0, 0, -426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -426, 0, -426, -426, -426, -426, 0, 0, 0, 0, 0, -426, -426, -426, -426, 0, -426, -426, -426, -426, 0, 0, 0, 0, -426, -426, -426, -426, -426, 0, 0, -426, -426, -426, -426, 0, -426, -426, -426, -426, -426, -426, -426, -426, -426, 0, 0, 0, -426, -426, 0, 0, 0, -426, -426, -426, -426, -426, -426, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1014 - -105, 0, 0, 0, 0, 0, -105, 0, -105, 0, 0, 0, -105, 0, 0, -105, 0, 0, 0, -105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -105, 0, -105, -105, -105, -105, 0, 0, 0, 0, 0, -105, -105, -105, -105, 0, -105, -105, -105, -105, -105, -105, 0, 0, -105, -105, -105, -105, -105, 0, 0, -105, -105, -105, -105, 0, -105, -105, -105, -105, -105, -105, -105, -105, -105, 0, 0, 0, -105, -105, 0, 0, 0, -105, -105, -105, -105, -105, -105, + 0, 0, 0, 0, 0, 0, 0, 1082, 0, 0, 0, 0, 0, 0, 1083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1015 - -489, 0, 0, 0, 0, 0, -489, 0, -489, 0, 0, 0, -489, 0, 0, -489, 0, 0, 0, -489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -489, 0, -489, -489, -489, -489, 0, 0, 0, 0, 0, -489, -489, -489, -489, 0, -489, -489, -489, -489, 0, 0, 0, 0, -489, -489, -489, -489, -489, 0, 0, -489, -489, -489, -489, 0, -489, -489, -489, -489, -489, -489, -489, -489, -489, 0, 0, 0, -489, -489, 0, 0, 0, -489, -489, -489, -489, -489, -489, + 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1016 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -797, 0, -797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1017 - 0, 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, 0, 0, 0, 1087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -338, 0, 0, 0, 0, -338, 0, -338, -338, 0, 0, 0, 0, 0, 0, 0, 0, -338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -338, 0, 0, 0, -338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -338, 0, -338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1018 - 0, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -755, 0, -755, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1019 - 0, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -792, 0, -792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -764, 0, -764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1020 - 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, -336, 0, -336, -336, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -336, 0, -336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 424, // State 1021 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1090, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1091, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1022 - 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1023 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -471, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1024 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1025 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1026 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 350, 0, 0, 0, 0, 0, -470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1027 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1028 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1029 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 350, 0, 0, 0, 0, 0, -467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -471, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1030 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1092, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1031 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1032 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -468, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -493, 0, 0, 0, 0, 0, -493, 0, -493, 0, 0, 0, -493, 0, 0, -493, 0, 0, 0, -493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -493, 0, -493, -493, -493, -493, 0, 0, 0, 0, 0, -493, -493, -493, -493, 0, -493, -493, -493, -493, 0, 0, 0, 0, -493, -493, -493, -493, -493, 0, 0, -493, -493, -493, -493, 0, -493, -493, -493, -493, -493, -493, -493, -493, -493, 0, 0, 0, -493, -493, 0, 0, 0, -493, -493, -493, -493, -493, -493, // State 1033 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1034 - 0, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -472, 0, -472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1035 - -490, 0, 0, 0, 0, 0, -490, 0, -490, 0, 0, 0, -490, 0, 0, -490, 0, 0, 0, -490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -490, 0, -490, -490, -490, -490, 0, 0, 0, 0, 0, -490, -490, -490, -490, 0, -490, -490, -490, -490, 0, 0, 0, 0, -490, -490, -490, -490, -490, 0, 0, -490, -490, -490, -490, 0, -490, -490, -490, -490, -490, -490, -490, -490, -490, 0, 0, 0, -490, -490, 0, 0, 0, -490, -490, -490, -490, -490, -490, + -363, 0, 0, 0, 0, 0, -363, 0, -363, 0, 0, 0, -363, 0, 0, -363, 0, 0, 0, -363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -363, 0, -363, -363, -363, -363, 0, 0, 0, 0, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, -363, -363, -363, -363, 0, 0, -363, -363, -363, -363, 0, -363, -363, -363, -363, -363, -363, -363, -363, -363, 0, 0, 0, -363, -363, 0, 0, 0, -363, -363, -363, -363, -363, -363, // State 1036 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1037 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -806, 0, -806, 0, 0, 0, -806, 0, 0, -806, 0, 0, 0, -806, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -806, 0, -806, -806, -806, -806, 0, 0, 0, 0, 0, -806, -806, -806, -806, 0, -806, -806, -806, -806, 0, 0, 0, 0, -806, -806, -806, -806, -806, 0, 0, -806, -806, -806, -806, 0, -806, -806, -806, -806, -806, -806, -806, -806, -806, 0, 0, 0, -806, -806, 0, 0, 0, -806, -806, -806, -806, -806, -806, // State 1038 - -361, 0, 0, 0, 0, 0, -361, 0, -361, 0, 0, 0, -361, 0, 0, -361, 0, 0, 0, -361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -361, 0, -361, -361, -361, -361, 0, 0, 0, 0, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, -361, -361, -361, -361, 0, 0, -361, -361, -361, -361, 0, -361, -361, -361, -361, -361, -361, -361, -361, -361, 0, 0, 0, -361, -361, 0, 0, 0, -361, -361, -361, -361, -361, -361, + 0, 0, 0, 0, 0, 0, -814, 0, -814, 0, 0, 0, -814, 0, 0, -814, 0, 0, 0, -814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -814, 0, -814, -814, -814, -814, 0, 0, 0, 0, 0, -814, -814, -814, -814, 0, -814, -814, -814, -814, 0, 0, 0, 0, -814, -814, -814, -814, -814, 0, 0, -814, -814, -814, -814, 0, -814, -814, -814, -814, -814, -814, -814, -814, -814, 0, 0, 0, -814, -814, 0, 0, 0, -814, -814, -814, -814, -814, -814, // State 1039 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1091, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, // State 1040 - 0, 0, 0, 0, 0, 0, -801, 0, -801, 0, 0, 0, -801, 0, 0, -801, 0, 0, 0, -801, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -801, 0, -801, -801, -801, -801, 0, 0, 0, 0, 0, -801, -801, -801, -801, 0, -801, -801, -801, -801, 0, 0, 0, 0, -801, -801, -801, -801, -801, 0, 0, -801, -801, -801, -801, 0, -801, -801, -801, -801, -801, -801, -801, -801, -801, 0, 0, 0, -801, -801, 0, 0, 0, -801, -801, -801, -801, -801, -801, + 0, 0, 0, 0, 0, 0, -811, 0, -811, 0, 0, 0, -811, 0, 0, -811, 0, 0, 0, -811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -811, 0, -811, -811, -811, -811, 0, 0, 0, 0, 0, -811, -811, -811, -811, 0, -811, -811, -811, -811, 0, 0, 0, 0, -811, -811, -811, -811, -811, 0, 0, -811, -811, -811, -811, 0, -811, -811, -811, -811, -811, -811, -811, -811, -811, 0, 0, 0, -811, -811, 0, 0, 0, -811, -811, -811, -811, -811, -811, // State 1041 - 0, 0, 0, 0, 0, 0, -809, 0, -809, 0, 0, 0, -809, 0, 0, -809, 0, 0, 0, -809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -809, 0, -809, -809, -809, -809, 0, 0, 0, 0, 0, -809, -809, -809, -809, 0, -809, -809, -809, -809, 0, 0, 0, 0, -809, -809, -809, -809, -809, 0, 0, -809, -809, -809, -809, 0, -809, -809, -809, -809, -809, -809, -809, -809, -809, 0, 0, 0, -809, -809, 0, 0, 0, -809, -809, -809, -809, -809, -809, + 0, -194, -194, 0, -194, 0, -194, 0, -194, -194, 0, 0, -194, 0, -194, -194, 0, 0, -194, 0, -194, -194, 0, 0, -221, 0, 0, -194, -194, 0, -194, 0, -194, -194, -194, -194, 0, 0, -194, 0, 0, 0, 0, -194, 0, -194, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, -194, -194, 0, 0, 0, -194, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, -194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1042 - 1095, 0, 0, 0, 0, 0, -133, 0, -133, 0, 0, 0, -133, 0, 0, -133, 0, 0, 0, -133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -133, -133, -133, -133, 0, 0, 0, 0, 0, -133, 0, -133, -133, 0, 0, -133, 0, -133, 0, 0, 0, 0, 0, -133, -133, 0, -133, 0, 0, -133, 0, -133, -133, 0, -133, -133, -133, 0, -133, 0, 0, -133, -133, 0, 0, 0, -133, 0, 0, 0, 0, -133, -133, -133, -133, -133, -133, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -904, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1043 - 0, 0, 0, 0, 0, 0, -806, 0, -806, 0, 0, 0, -806, 0, 0, -806, 0, 0, 0, -806, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -806, 0, -806, -806, -806, -806, 0, 0, 0, 0, 0, -806, -806, -806, -806, 0, -806, -806, -806, -806, 0, 0, 0, 0, -806, -806, -806, -806, -806, 0, 0, -806, -806, -806, -806, 0, -806, -806, -806, -806, -806, -806, -806, -806, -806, 0, 0, 0, -806, -806, 0, 0, 0, -806, -806, -806, -806, -806, -806, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1092, 0, 0, 0, 0, 0, 0, 0, 0, 0, -675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1044 - 0, -192, -192, 0, -192, 0, -192, 0, -192, -192, 0, 0, -192, 0, -192, -192, 0, 0, -192, 0, -192, -192, 0, 0, -219, 0, 0, -192, -192, 0, -192, 0, -192, -192, -192, -192, 0, -192, 0, 0, 0, 0, -192, 0, -192, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, -192, -192, 0, 0, 0, -192, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1094, 0, 0, 0, 0, 0, 0, 0, 0, 0, -666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1045 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1046 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1096, 0, 0, 0, 0, 0, 0, 0, 0, 0, -671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1047 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1098, 0, 0, 0, 0, 0, 0, 0, 0, 0, -662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1095, 0, 0, 0, 0, 0, 0, 0, 0, 0, -671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1048 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1049 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -399, 0, 0, 0, 0, 0, -399, 0, -399, 0, 0, 0, -399, 0, 0, -399, 0, 0, 0, -399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -399, 0, -399, -399, -399, -399, 0, 0, 0, 0, 0, -399, -399, -399, -399, 0, -399, -399, -399, -399, 0, 0, 0, 0, -399, -399, -399, -399, -399, 0, 0, -399, -399, -399, -399, 0, -399, -399, -399, -399, -399, -399, -399, -399, -399, 0, 0, 0, -399, -399, 0, 0, 0, -399, -399, -399, -399, -399, -399, // State 1050 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1099, 0, 0, 0, 0, 0, 0, 0, 0, 0, -667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -406, 0, 0, 0, 0, 0, -406, 0, -406, 0, 0, 0, -406, 0, 0, -406, 0, 0, 0, -406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -406, 0, -406, -406, -406, -406, 0, 0, 0, 0, 0, -406, -406, -406, -406, 0, -406, -406, -406, -406, 0, 0, 0, 0, -406, -406, -406, -406, -406, 0, 0, -406, -406, -406, -406, 0, -406, -406, -406, -406, -406, -406, -406, -406, -406, 0, 0, 0, -406, -406, 0, 0, 0, -406, -406, -406, -406, -406, -406, // State 1051 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -396, 0, 0, 0, 0, 0, -396, 0, -396, 0, 0, 0, -396, 0, 0, -396, 0, 0, 0, -396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -396, 0, -396, -396, -396, -396, 0, 0, 0, 0, 0, -396, -396, -396, -396, 0, -396, -396, -396, -396, 0, 0, 0, 0, -396, -396, -396, -396, -396, 0, 0, -396, -396, -396, -396, 0, -396, -396, -396, -396, -396, -396, -396, -396, -396, 0, 0, 0, -396, -396, 0, 0, 0, -396, -396, -396, -396, -396, -396, // State 1052 - -397, 0, 0, 0, 0, 0, -397, 0, -397, 0, 0, 0, -397, 0, 0, -397, 0, 0, 0, -397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -397, 0, -397, -397, -397, -397, 0, 0, 0, 0, 0, -397, -397, -397, -397, 0, -397, -397, -397, -397, 0, 0, 0, 0, -397, -397, -397, -397, -397, 0, 0, -397, -397, -397, -397, 0, -397, -397, -397, -397, -397, -397, -397, -397, -397, 0, 0, 0, -397, -397, 0, 0, 0, -397, -397, -397, -397, -397, -397, + 0, 0, 0, 0, 0, 0, 0, -595, 0, 0, 0, 0, 0, 0, 1098, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1053 - -266, 0, 0, 0, 0, 0, -266, 0, -266, 0, 0, 0, -266, 0, 0, -266, 0, 0, 0, -266, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -266, 0, -266, -266, -266, -266, 0, 0, 0, 0, 0, -266, -266, -266, -266, 0, -266, -266, -266, -266, 0, 0, 0, 0, -266, -266, -266, -266, -266, 0, 0, -266, -266, -266, -266, 0, -266, -266, -266, -266, -266, -266, -266, -266, -266, 0, 0, 0, -266, -266, 0, 0, 0, -266, -266, -266, -266, -266, -266, + 0, 0, 0, 0, 0, 0, 0, -586, 0, 0, 0, 0, 0, 0, 1100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1054 - -404, 0, 0, 0, 0, 0, -404, 0, -404, 0, 0, 0, -404, 0, 0, -404, 0, 0, 0, -404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -404, 0, -404, -404, -404, -404, 0, 0, 0, 0, 0, -404, -404, -404, -404, 0, -404, -404, -404, -404, 0, 0, 0, 0, -404, -404, -404, -404, -404, 0, 0, -404, -404, -404, -404, 0, -404, -404, -404, -404, -404, -404, -404, -404, -404, 0, 0, 0, -404, -404, 0, 0, 0, -404, -404, -404, -404, -404, -404, + 0, 0, 0, 0, 0, 0, 0, -562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1055 - -394, 0, 0, 0, 0, 0, -394, 0, -394, 0, 0, 0, -394, 0, 0, -394, 0, 0, 0, -394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -394, 0, -394, -394, -394, -394, 0, 0, 0, 0, 0, -394, -394, -394, -394, 0, -394, -394, -394, -394, 0, 0, 0, 0, -394, -394, -394, -394, -394, 0, 0, -394, -394, -394, -394, 0, -394, -394, -394, -394, -394, -394, -394, -394, -394, 0, 0, 0, -394, -394, 0, 0, 0, -394, -394, -394, -394, -394, -394, + 0, 0, 0, 0, 0, 0, 0, -618, 0, 0, 0, 0, 0, 0, 1101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1056 - 0, 0, 0, 0, 0, 0, 0, -591, 0, 0, 0, 0, 0, 0, 1102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1057 - 0, 0, 0, 0, 0, 0, 0, -582, 0, 0, 0, 0, 0, 0, 1104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -608, 0, 0, 0, 0, 0, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1058 - 0, 0, 0, 0, 0, 0, 0, -558, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -621, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1059 - 0, 0, 0, 0, 0, 0, 0, -614, 0, 0, 0, 0, 0, 0, 1105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -394, 0, 0, 0, 0, 0, -394, 0, -394, 0, 0, 0, -394, 0, 0, -394, 0, 0, 0, -394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -394, 0, -394, -394, -394, -394, 0, 0, 0, 0, 0, -394, -394, -394, -394, 0, -394, -394, -394, -394, 0, 0, 0, 0, -394, -394, -394, -394, -394, 0, 0, -394, -394, -394, -394, 0, -394, -394, -394, -394, -394, -394, -394, -394, -394, 0, 0, 0, -394, -394, 0, 0, 0, -394, -394, -394, -394, -394, -394, // State 1060 - 0, 0, 0, 0, 0, 0, 0, -610, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -106, 0, 0, 0, 0, 0, -106, 0, -106, 0, 0, 0, -106, 0, 0, -106, 0, 0, 0, -106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -106, 0, -106, -106, -106, -106, 0, 0, 0, 0, 0, -106, -106, -106, -106, 0, -106, -106, -106, -106, -106, -106, 0, 0, -106, -106, -106, -106, -106, 0, 0, -106, -106, -106, -106, 0, -106, -106, -106, -106, -106, -106, -106, -106, -106, 0, 0, 0, -106, -106, 0, 0, 0, -106, -106, -106, -106, -106, -106, // State 1061 - 0, 0, 0, 0, 0, 0, 0, -604, 0, 0, 0, 0, 0, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -867, 0, -867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1062 - 0, 0, 0, 0, 0, 0, 0, -617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1063 - -392, 0, 0, 0, 0, 0, -392, 0, -392, 0, 0, 0, -392, 0, 0, -392, 0, 0, 0, -392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -392, 0, -392, -392, -392, -392, 0, 0, 0, 0, 0, -392, -392, -392, -392, 0, -392, -392, -392, -392, 0, 0, 0, 0, -392, -392, -392, -392, -392, 0, 0, -392, -392, -392, -392, 0, -392, -392, -392, -392, -392, -392, -392, -392, -392, 0, 0, 0, -392, -392, 0, 0, 0, -392, -392, -392, -392, -392, -392, + 0, 0, 0, 0, 0, 0, -488, -265, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, -488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1064 - -106, 0, 0, 0, 0, 0, -106, 0, -106, 0, 0, 0, -106, 0, 0, -106, 0, 0, 0, -106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -106, 0, -106, -106, -106, -106, 0, 0, 0, 0, 0, -106, -106, -106, -106, 0, -106, -106, -106, -106, -106, -106, 0, 0, -106, -106, -106, -106, -106, 0, 0, -106, -106, -106, -106, 0, -106, -106, -106, -106, -106, -106, -106, -106, -106, 0, 0, 0, -106, -106, 0, 0, 0, -106, -106, -106, -106, -106, -106, + 0, 0, 0, 0, 0, 0, 0, -525, 0, 0, 0, 0, 0, 0, -525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1065 - 0, 0, 0, 0, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -862, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -862, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1105, 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1066 - 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, -154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1106, 0, 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1067 - 0, 0, 0, 0, 0, 0, -485, -263, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, -485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -533, 0, 0, 0, 0, 0, 0, -533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1068 - 0, 0, 0, 0, 0, 0, 0, -521, 0, 0, 0, 0, 0, 0, -521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1069 - 0, 0, 0, 0, 0, 0, 0, 1109, 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -489, -489, 0, 0, 0, 0, 0, 0, -489, 0, 0, 0, -489, 0, 0, 0, 0, 0, -489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -489, 0, 0, 0, -489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -489, 0, -489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1070 - 0, 0, 0, 0, 0, 0, 0, 1110, 0, 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1107, 0, 0, 0, 0, 0, 0, 382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1071 - 0, 0, 0, 0, 0, 0, 0, -529, 0, 0, 0, 0, 0, 0, -529, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1108, 0, 0, 0, 0, 0, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1072 - 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, -287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1073 - 0, 0, 0, 0, 0, 0, -486, -486, 0, 0, 0, 0, 0, 0, -486, 0, 0, 0, -486, 0, 0, 0, 0, 0, -486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -486, 0, 0, 0, -486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -486, 0, -486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -490, -490, 0, 0, 0, 0, 0, 0, -490, 0, 0, 0, -490, 0, 0, 0, 0, 0, -490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -490, 0, 0, 0, -490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -490, 0, -490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1074 - 0, 0, 0, 0, 0, 0, 0, 1111, 0, 0, 0, 0, 0, 0, 382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1075 - 0, 0, 0, 0, 0, 0, 0, 1112, 0, 0, 0, 0, 0, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -869, 0, 0, 0, 0, 0, 0, 0, 0, 0, -869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1076 - 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -483, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1077 - 0, 0, 0, 0, 0, 0, -487, -487, 0, 0, 0, 0, 0, 0, -487, 0, 0, 0, -487, 0, 0, 0, 0, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -487, 0, 0, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -487, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1078 - 0, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -868, 0, -868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1079 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -864, 0, 0, 0, 0, 0, 0, 0, 0, 0, -864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -870, 0, 0, 0, 0, 0, 0, 0, 0, 0, -870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -870, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1080 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1110, 0, 0, 0, 0, 0, 0, 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1081 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1082 - 0, 0, 0, 0, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -863, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -863, 0, -863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -127, 1112, -127, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, 0, -127, -127, // State 1083 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -865, 0, 0, 0, 0, 0, 0, 0, 0, 0, -865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1084 - 0, 0, 0, 0, 0, 0, 0, 1114, 0, 0, 0, 0, 0, 0, 1115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -766, 0, -766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1085 - 0, 0, 0, 0, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -754, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -754, 0, -754, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -127, 0, -127, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, -127, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, 0, -127, -127, // State 1086 - 0, 0, 0, 0, 0, 0, -127, 1116, -127, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, 0, -127, -127, + 0, 0, 0, 0, 0, 0, 0, -763, 0, 0, 0, 0, 0, 0, -763, 0, 0, 0, 0, 0, 0, 0, 0, 0, -763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -763, 0, 0, 0, -763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -763, 0, -763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1087 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1088 - 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1089 - 0, 0, 0, 0, 0, 0, -127, 0, -127, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, -127, -127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -127, 0, 0, 0, 0, 0, 0, 0, 0, -127, -127, -127, 0, -127, -127, + -360, 0, 0, 0, 0, 0, -360, 0, -360, 0, 0, 0, -360, 0, 0, -360, 0, 0, 0, -360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -360, 0, -360, -360, -360, -360, 0, 0, 0, 0, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, -360, -360, -360, -360, 0, 0, -360, -360, -360, -360, 0, -360, -360, -360, -360, -360, -360, -360, -360, -360, 0, 0, 0, -360, -360, 0, 0, 0, -360, -360, -360, -360, -360, -360, // State 1090 - 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -759, 0, -759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -812, 0, -812, 0, 0, 0, -812, 0, 0, -812, 0, 0, 0, -812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -812, 0, -812, -812, -812, -812, 0, 0, 0, 0, 0, -812, -812, -812, -812, 0, -812, -812, -812, -812, 0, 0, 0, 0, -812, -812, -812, -812, -812, 0, 0, -812, -812, -812, -812, 0, -812, -812, -812, -812, -812, -812, -812, -812, -812, 0, 0, 0, -812, -812, 0, 0, 0, -812, -812, -812, -812, -812, -812, // State 1091 - 0, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -474, 0, -474, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1092 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1123, 0, 0, 0, 0, 0, 0, 0, 0, 0, -672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1093 - -358, 0, 0, 0, 0, 0, -358, 0, -358, 0, 0, 0, -358, 0, 0, -358, 0, 0, 0, -358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -358, 0, -358, -358, -358, -358, 0, 0, 0, 0, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, -358, -358, -358, -358, 0, 0, -358, -358, -358, -358, 0, -358, -358, -358, -358, -358, -358, -358, -358, -358, 0, 0, 0, -358, -358, 0, 0, 0, -358, -358, -358, -358, -358, -358, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1094 - 0, 0, 0, 0, 0, 0, -807, 0, -807, 0, 0, 0, -807, 0, 0, -807, 0, 0, 0, -807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -807, 0, -807, -807, -807, -807, 0, 0, 0, 0, 0, -807, -807, -807, -807, 0, -807, -807, -807, -807, 0, 0, 0, 0, -807, -807, -807, -807, -807, 0, 0, -807, -807, -807, -807, 0, -807, -807, -807, -807, -807, -807, -807, -807, -807, 0, 0, 0, -807, -807, 0, 0, 0, -807, -807, -807, -807, -807, -807, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -644, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1095 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -644, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -398, 0, 0, 0, 0, 0, -398, 0, -398, 0, 0, 0, -398, 0, 0, -398, 0, 0, 0, -398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -398, 0, -398, -398, -398, -398, 0, 0, 0, 0, 0, -398, -398, -398, -398, 0, -398, -398, -398, -398, 0, 0, 0, 0, -398, -398, -398, -398, -398, 0, 0, -398, -398, -398, -398, 0, -398, -398, -398, -398, -398, -398, -398, -398, -398, 0, 0, 0, -398, -398, 0, 0, 0, -398, -398, -398, -398, -398, -398, // State 1096 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1127, 0, 0, 0, 0, 0, 0, 0, 0, 0, -668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -392, 0, 0, 0, 0, 0, -392, 0, -392, 0, 0, 0, -392, 0, 0, -392, 0, 0, 0, -392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -392, 0, -392, -392, -392, -392, 0, 0, 0, 0, 0, -392, -392, -392, -392, 0, -392, -392, -392, -392, 0, 0, 0, 0, -392, -392, -392, -392, -392, 0, 0, -392, -392, -392, -392, 0, -392, -392, -392, -392, -392, -392, -392, -392, -392, 0, 0, 0, -392, -392, 0, 0, 0, -392, -392, -392, -392, -392, -392, // State 1097 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -635, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1098 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -592, 0, 0, 0, 0, 0, 0, 1124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1099 - -396, 0, 0, 0, 0, 0, -396, 0, -396, 0, 0, 0, -396, 0, 0, -396, 0, 0, 0, -396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -396, 0, -396, -396, -396, -396, 0, 0, 0, 0, 0, -396, -396, -396, -396, 0, -396, -396, -396, -396, 0, 0, 0, 0, -396, -396, -396, -396, -396, 0, 0, -396, -396, -396, -396, 0, -396, -396, -396, -396, -396, -396, -396, -396, -396, 0, 0, 0, -396, -396, 0, 0, 0, -396, -396, -396, -396, -396, -396, + 0, 0, 0, 0, 0, 0, 0, -559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1100 - -390, 0, 0, 0, 0, 0, -390, 0, -390, 0, 0, 0, -390, 0, 0, -390, 0, 0, 0, -390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -390, 0, -390, -390, -390, -390, 0, 0, 0, 0, 0, -390, -390, -390, -390, 0, -390, -390, -390, -390, 0, 0, 0, 0, -390, -390, -390, -390, -390, 0, 0, -390, -390, -390, -390, 0, -390, -390, -390, -390, -390, -390, -390, -390, -390, 0, 0, 0, -390, -390, 0, 0, 0, -390, -390, -390, -390, -390, -390, + 0, 0, 0, 0, 0, 0, 0, -615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1101 - 0, 0, 0, 0, 0, 0, 0, -564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -609, 0, 0, 0, 0, 0, 0, 385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1102 - 0, 0, 0, 0, 0, 0, 0, -588, 0, 0, 0, 0, 0, 0, 1128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -605, 0, 0, 0, 0, 0, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1103 - 0, 0, 0, 0, 0, 0, 0, -555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -590, 0, 0, 0, 0, 0, 0, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1104 - 0, 0, 0, 0, 0, 0, 0, -611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1105 - 0, 0, 0, 0, 0, 0, 0, -605, 0, 0, 0, 0, 0, 0, 385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1106 - 0, 0, 0, 0, 0, 0, 0, -601, 0, 0, 0, 0, 0, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -286, 0, -286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1107 - 0, 0, 0, 0, 0, 0, 0, -586, 0, 0, 0, 0, 0, 0, 1133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1108 - 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -277, 0, -277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -482, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1109 - 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -762, 0, -762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1110 - 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -284, 0, -284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -128, 1140, -128, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, -128, -128, // State 1111 - 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -760, 0, -760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1112 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, -128, -128, // State 1113 - 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -758, 0, -758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -765, 0, -765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1114 - 0, 0, 0, 0, 0, 0, -128, 1144, -128, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, -128, -128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1115 - 0, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -756, 0, -756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1116 - 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, -128, -128, + 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1117 - 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1118 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -479, 0, -479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1119 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -858, 0, 0, 0, 0, 0, -858, 0, -858, 0, 0, 0, -858, 0, 0, -858, 0, 0, 0, -858, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -858, 0, -858, -858, -858, -858, 0, 0, 0, 0, 0, -858, -858, -858, -858, 0, -858, -858, -858, -858, 0, 0, 0, 0, -858, -858, -858, -858, -858, 0, 0, -858, -858, -858, -858, 0, -858, -858, -858, -858, -858, -858, -858, -858, -858, 0, 0, 0, -858, -858, 0, 0, 0, -858, -858, -858, -858, -858, -858, // State 1120 - 0, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -473, 0, -473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -862, 0, 0, 0, 0, 0, -862, 0, -862, 0, 0, 0, -862, 0, 0, -862, 0, 0, 0, -862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -862, 0, -862, -862, -862, -862, 0, 0, 0, 0, 0, -862, -862, -862, -862, 0, -862, -862, -862, -862, 0, 0, 0, 0, -862, -862, -862, -862, -862, 0, 0, -862, -862, -862, -862, 0, -862, -862, -862, -862, -862, -862, -862, -862, -862, 0, 0, 0, -862, -862, 0, 0, 0, -862, -862, -862, -862, -862, -862, // State 1121 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -364, 0, 0, 0, 0, 0, -364, 0, -364, 0, 0, 0, -364, 0, 0, -364, 0, 0, 0, -364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -364, 0, -364, -364, -364, -364, 0, 0, 0, 0, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, -364, -364, -364, -364, 0, 0, -364, -364, -364, -364, 0, -364, -364, -364, -364, -364, -364, -364, -364, -364, 0, 0, 0, -364, -364, 0, 0, 0, -364, -364, -364, -364, -364, -364, // State 1122 - 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -476, 0, -476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1123 - -853, 0, 0, 0, 0, 0, -853, 0, -853, 0, 0, 0, -853, 0, 0, -853, 0, 0, 0, -853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -853, 0, -853, -853, -853, -853, 0, 0, 0, 0, 0, -853, -853, -853, -853, 0, -853, -853, -853, -853, 0, 0, 0, 0, -853, -853, -853, -853, -853, 0, 0, -853, -853, -853, -853, 0, -853, -853, -853, -853, -853, -853, -853, -853, -853, 0, 0, 0, -853, -853, 0, 0, 0, -853, -853, -853, -853, -853, -853, + 0, 0, 0, 0, 0, 0, 0, -565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1124 - -857, 0, 0, 0, 0, 0, -857, 0, -857, 0, 0, 0, -857, 0, 0, -857, 0, 0, 0, -857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -857, 0, -857, -857, -857, -857, 0, 0, 0, 0, 0, -857, -857, -857, -857, 0, -857, -857, -857, -857, 0, 0, 0, 0, -857, -857, -857, -857, -857, 0, 0, -857, -857, -857, -857, 0, -857, -857, -857, -857, -857, -857, -857, -857, -857, 0, 0, 0, -857, -857, 0, 0, 0, -857, -857, -857, -857, -857, -857, + 0, 0, 0, 0, 0, 0, 0, -606, 0, 0, 0, 0, 0, 0, 388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1125 - -362, 0, 0, 0, 0, 0, -362, 0, -362, 0, 0, 0, -362, 0, 0, -362, 0, 0, 0, -362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -362, 0, -362, -362, -362, -362, 0, 0, 0, 0, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, -362, -362, -362, -362, 0, 0, -362, -362, -362, -362, 0, -362, -362, -362, -362, -362, -362, -362, -362, -362, 0, 0, 0, -362, -362, 0, 0, 0, -362, -362, -362, -362, -362, -362, + 0, 0, 0, 0, 0, 0, 0, -591, 0, 0, 0, 0, 0, 0, 1145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1126 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -596, 0, 0, 0, 0, 0, 0, 1146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1127 - 0, 0, 0, 0, 0, 0, 0, -561, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -587, 0, 0, 0, 0, 0, 0, 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1128 - 0, 0, 0, 0, 0, 0, 0, -602, 0, 0, 0, 0, 0, 0, 388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -563, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1129 - 0, 0, 0, 0, 0, 0, 0, -587, 0, 0, 0, 0, 0, 0, 1149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -486, 0, 0, 0, 0, 0, 0, -486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1130 - 0, 0, 0, 0, 0, 0, 0, -592, 0, 0, 0, 0, 0, 0, 1150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1131 - 0, 0, 0, 0, 0, 0, 0, -583, 0, 0, 0, 0, 0, 0, 1152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -526, 0, 0, 0, 0, 0, 0, -526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1132 - 0, 0, 0, 0, 0, 0, 0, -559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -278, 0, -278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1133 - 0, 0, 0, 0, 0, 0, 0, -483, 0, 0, 0, 0, 0, 0, -483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1149, 0, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1134 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -534, 0, 0, 0, 0, 0, 0, -534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1135 - 0, 0, 0, 0, 0, 0, 0, -522, 0, 0, 0, 0, 0, 0, -522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1136 - 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -276, 0, -276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -285, 0, -285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1137 - 0, 0, 0, 0, 0, 0, 0, 1153, 0, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1150, 0, 0, 0, 0, 0, 0, 390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1138 - 0, 0, 0, 0, 0, 0, 0, -530, 0, 0, 0, 0, 0, 0, -530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1139 - 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -761, 0, -761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1140 - 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -283, 0, -283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1141 - 0, 0, 0, 0, 0, 0, 0, 1154, 0, 0, 0, 0, 0, 0, 390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1142 - 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -597, 0, 0, 0, 0, 0, 0, 1153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1143 - 0, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -757, 0, -757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -588, 0, 0, 0, 0, 0, 0, 1155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1144 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1145 - 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -475, 0, -475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -569, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1146 - 0, 0, 0, 0, 0, 0, 0, -593, 0, 0, 0, 0, 0, 0, 1157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -593, 0, 0, 0, 0, 0, 0, 1156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1147 - 0, 0, 0, 0, 0, 0, 0, -584, 0, 0, 0, 0, 0, 0, 1159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1148 - 0, 0, 0, 0, 0, 0, 0, -560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -275, 0, -275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1149 - 0, 0, 0, 0, 0, 0, 0, -565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -282, 0, -282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1150 - 0, 0, 0, 0, 0, 0, 0, -589, 0, 0, 0, 0, 0, 0, 1160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1151 - 0, 0, 0, 0, 0, 0, 0, -556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -481, 0, -481, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1152 - 0, 0, 0, 0, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -273, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -273, 0, -273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -570, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1153 - 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -280, 0, -280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -594, 0, 0, 0, 0, 0, 0, 1160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1154 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -561, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1155 - 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -478, 0, -478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1156 - 0, 0, 0, 0, 0, 0, 0, -566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -274, 0, -274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1157 - 0, 0, 0, 0, 0, 0, 0, -590, 0, 0, 0, 0, 0, 0, 1164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -281, 0, -281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1158 - 0, 0, 0, 0, 0, 0, 0, -557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -480, 0, -480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 1159 - 0, 0, 0, 0, 0, 0, 0, -562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // State 1160 - 0, 0, 0, 0, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -272, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -272, 0, -272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // State 1161 - 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -279, 0, -279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // State 1162 - 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -477, 0, -477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // State 1163 - 0, 0, 0, 0, 0, 0, 0, -563, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; fn __action(state: i16, integer: usize) -> i16 { - __ACTION[(state as usize) * 96 + integer] + __ACTION[(state as usize) * 97 + integer] } const __EOF_ACTION: &[i16] = &[ // State 0 @@ -2477,23 +2471,23 @@ mod __parse__Top { // State 1 0, // State 2 - -744, + -748, // State 3 0, // State 4 0, // State 5 - -766, + -770, // State 6 - -315, + -249, // State 7 - -851, + -317, // State 8 - -156, + -856, // State 9 - -168, + -156, // State 10 - 0, + -170, // State 11 0, // State 12 @@ -2509,9 +2503,9 @@ mod __parse__Top { // State 17 0, // State 18 - -850, - // State 19 0, + // State 19 + -855, // State 20 0, // State 21 @@ -2523,15 +2517,15 @@ mod __parse__Top { // State 24 0, // State 25 - -314, - // State 26 0, + // State 26 + -316, // State 27 0, // State 28 - -419, - // State 29 0, + // State 29 + -421, // State 30 0, // State 31 @@ -2551,7 +2545,7 @@ mod __parse__Top { // State 38 0, // State 39 - 0, + -248, // State 40 0, // State 41 @@ -2601,15 +2595,15 @@ mod __parse__Top { // State 63 0, // State 64 - -155, + 0, // State 65 - -167, + 0, // State 66 0, // State 67 - 0, + -155, // State 68 - 0, + -169, // State 69 0, // State 70 @@ -2617,13 +2611,13 @@ mod __parse__Top { // State 71 0, // State 72 - -765, + 0, // State 73 0, // State 74 0, // State 75 - 0, + -769, // State 76 0, // State 77 @@ -2879,19 +2873,19 @@ mod __parse__Top { // State 202 0, // State 203 - -425, + 0, // State 204 - -856, + 0, // State 205 - -860, + 0, // State 206 0, // State 207 - 0, + -427, // State 208 - 0, + -861, // State 209 - 0, + -865, // State 210 0, // State 211 @@ -3253,81 +3247,81 @@ mod __parse__Top { // State 389 0, // State 390 - -917, + -922, // State 391 - -182, + -184, // State 392 - -911, + -916, // State 393 - -542, + -546, // State 394 - -238, + -240, // State 395 - -247, + -745, // State 396 - -741, + -508, // State 397 - -504, + -185, // State 398 - -183, + -834, // State 399 - -829, + -186, // State 400 - -184, + -839, // State 401 - -834, - // State 402 -160, + // State 402 + -422, // State 403 - -420, + -838, // State 404 - -833, + -383, // State 405 - -381, + -851, // State 406 - -846, + -850, // State 407 - -845, + -537, // State 408 - -533, + -368, // State 409 - -366, + 0, // State 410 0, // State 411 - 0, + -212, // State 412 -210, // State 413 - -208, + -211, // State 414 -209, // State 415 - -207, - // State 416 0, + // State 416 + -335, // State 417 - -333, + -334, // State 418 - -332, + -333, // State 419 - -331, + -425, // State 420 - -423, - // State 421 -139, + // State 421 + -545, // State 422 - -541, - // State 423 -159, - // State 424 + // State 423 -140, + // State 424 + 0, // State 425 0, // State 426 0, // State 427 - 0, + -241, // State 428 0, // State 429 @@ -3347,7 +3341,7 @@ mod __parse__Top { // State 436 0, // State 437 - -852, + -857, // State 438 -88, // State 439 @@ -3367,7 +3361,7 @@ mod __parse__Top { // State 446 0, // State 447 - -380, + -382, // State 448 0, // State 449 @@ -3381,11 +3375,11 @@ mod __parse__Top { // State 453 0, // State 454 - -198, + 0, // State 455 - -791, + -200, // State 456 - 0, + -796, // State 457 0, // State 458 @@ -3397,9 +3391,9 @@ mod __parse__Top { // State 461 0, // State 462 - -186, + 0, // State 463 - -246, + -188, // State 464 0, // State 465 @@ -3413,7 +3407,7 @@ mod __parse__Top { // State 469 0, // State 470 - -503, + -507, // State 471 0, // State 472 @@ -3429,13 +3423,13 @@ mod __parse__Top { // State 477 0, // State 478 - -203, + -205, // State 479 0, // State 480 - -325, + -327, // State 481 - -745, + -749, // State 482 0, // State 483 @@ -3445,21 +3439,21 @@ mod __parse__Top { // State 485 0, // State 486 - -321, + -323, // State 487 - -324, + -326, // State 488 0, // State 489 - -319, + -321, // State 490 0, // State 491 0, // State 492 - -318, - // State 493 0, + // State 493 + -320, // State 494 0, // State 495 @@ -3469,19 +3463,19 @@ mod __parse__Top { // State 497 0, // State 498 - -322, - // State 499 0, + // State 499 + -324, // State 500 - -320, + 0, // State 501 - -323, + -322, // State 502 - 0, + -325, // State 503 - -750, - // State 504 0, + // State 504 + -754, // State 505 0, // State 506 @@ -3503,9 +3497,9 @@ mod __parse__Top { // State 514 0, // State 515 - -241, + -164, // State 516 - 0, + -243, // State 517 0, // State 518 @@ -3515,27 +3509,27 @@ mod __parse__Top { // State 520 0, // State 521 - -740, + 0, // State 522 - -142, + -744, // State 523 - 0, + -142, // State 524 0, // State 525 - -365, + 0, // State 526 - -89, + -367, // State 527 - -534, + -89, // State 528 - 0, + -538, // State 529 - -828, + 0, // State 530 - -910, + -833, // State 531 - 0, + -915, // State 532 0, // State 533 @@ -3543,19 +3537,19 @@ mod __parse__Top { // State 534 0, // State 535 - -195, + 0, // State 536 - -189, + -197, // State 537 - -199, + -191, // State 538 - 0, + -201, // State 539 0, // State 540 - -185, - // State 541 0, + // State 541 + -187, // State 542 0, // State 543 @@ -3565,17 +3559,17 @@ mod __parse__Top { // State 545 0, // State 546 - -452, - // State 547 0, + // State 547 + -457, // State 548 - -202, - // State 549 0, + // State 549 + -204, // State 550 - -205, - // State 551 0, + // State 551 + -207, // State 552 0, // State 553 @@ -3611,13 +3605,13 @@ mod __parse__Top { // State 568 0, // State 569 - -748, + 0, // State 570 0, // State 571 0, // State 572 - 0, + -752, // State 573 0, // State 574 @@ -3735,77 +3729,77 @@ mod __parse__Top { // State 630 0, // State 631 - -239, + 0, // State 632 0, // State 633 0, // State 634 - 0, + -166, // State 635 - 0, + -163, // State 636 - -240, + 0, // State 637 0, // State 638 - -143, + 0, // State 639 0, // State 640 - -200, + -242, // State 641 0, // State 642 - 0, + -143, // State 643 - -197, - // State 644 0, + // State 644 + -202, // State 645 - -191, + 0, // State 646 0, // State 647 - 0, + -199, // State 648 - -188, + 0, // State 649 - -201, + -193, // State 650 0, // State 651 0, // State 652 - -187, + -190, // State 653 - 0, + -203, // State 654 0, // State 655 - -451, - // State 656 0, + // State 656 + -189, // State 657 0, // State 658 0, // State 659 - 0, + -456, // State 660 - -204, + 0, // State 661 - -206, + 0, // State 662 0, // State 663 0, // State 664 - 0, + -206, // State 665 - 0, + -208, // State 666 - -749, + 0, // State 667 0, // State 668 @@ -3813,7 +3807,7 @@ mod __parse__Top { // State 669 0, // State 670 - 0, + -753, // State 671 0, // State 672 @@ -3823,7 +3817,7 @@ mod __parse__Top { // State 674 0, // State 675 - -746, + 0, // State 676 0, // State 677 @@ -3833,7 +3827,7 @@ mod __parse__Top { // State 679 0, // State 680 - 0, + -750, // State 681 0, // State 682 @@ -3891,37 +3885,37 @@ mod __parse__Top { // State 708 0, // State 709 - 0, + -165, // State 710 0, // State 711 - -832, + 0, // State 712 0, // State 713 0, // State 714 - -193, + 0, // State 715 0, // State 716 - -194, - // State 717 0, + // State 717 + -837, // State 718 0, // State 719 0, // State 720 - 0, + -195, // State 721 0, // State 722 - 0, + -196, // State 723 0, // State 724 - -747, + 0, // State 725 0, // State 726 @@ -3933,9 +3927,9 @@ mod __parse__Top { // State 729 0, // State 730 - 0, + -751, // State 731 - -269, + 0, // State 732 0, // State 733 @@ -3947,7 +3941,7 @@ mod __parse__Top { // State 736 0, // State 737 - 0, + -271, // State 738 0, // State 739 @@ -3995,31 +3989,31 @@ mod __parse__Top { // State 760 0, // State 761 - -825, + 0, // State 762 0, // State 763 - -359, + 0, // State 764 - -363, + 0, // State 765 0, // State 766 0, // State 767 - -889, + -830, // State 768 0, // State 769 - 0, + -361, // State 770 - 0, + -365, // State 771 0, // State 772 0, // State 773 - 0, + -894, // State 774 0, // State 775 @@ -4029,7 +4023,7 @@ mod __parse__Top { // State 777 0, // State 778 - -909, + 0, // State 779 0, // State 780 @@ -4039,7 +4033,7 @@ mod __parse__Top { // State 782 0, // State 783 - 0, + -914, // State 784 0, // State 785 @@ -4063,9 +4057,9 @@ mod __parse__Top { // State 794 0, // State 795 - -196, + 0, // State 796 - -190, + 0, // State 797 0, // State 798 @@ -4073,9 +4067,9 @@ mod __parse__Top { // State 799 0, // State 800 - 0, + -198, // State 801 - 0, + -192, // State 802 0, // State 803 @@ -4083,7 +4077,7 @@ mod __parse__Top { // State 804 0, // State 805 - -271, + 0, // State 806 0, // State 807 @@ -4091,23 +4085,23 @@ mod __parse__Top { // State 808 0, // State 809 - -908, - // State 810 0, + // State 810 + -273, // State 811 - -268, + 0, // State 812 0, // State 813 0, // State 814 - 0, + -913, // State 815 - 0, + -267, // State 816 - 0, + -270, // State 817 - -407, + 0, // State 818 0, // State 819 @@ -4115,7 +4109,7 @@ mod __parse__Top { // State 820 0, // State 821 - 0, + -409, // State 822 0, // State 823 @@ -4125,7 +4119,7 @@ mod __parse__Top { // State 825 0, // State 826 - -427, + 0, // State 827 0, // State 828 @@ -4133,27 +4127,27 @@ mod __parse__Top { // State 829 0, // State 830 - -826, + -429, // State 831 0, // State 832 - -823, + 0, // State 833 - -360, - // State 834 0, + // State 834 + -831, // State 835 0, // State 836 - -364, + -828, // State 837 - 0, + -362, // State 838 0, // State 839 0, // State 840 - 0, + -366, // State 841 0, // State 842 @@ -4195,11 +4189,11 @@ mod __parse__Top { // State 860 0, // State 861 - -192, + 0, // State 862 0, // State 863 - 0, + -194, // State 864 0, // State 865 @@ -4215,21 +4209,21 @@ mod __parse__Top { // State 870 0, // State 871 - -270, - // State 872 0, + // State 872 + -269, // State 873 - 0, + -272, // State 874 - -409, - // State 875 0, + // State 875 + -411, // State 876 - -399, - // State 877 0, + // State 877 + -401, // State 878 - 0, + -266, // State 879 0, // State 880 @@ -4237,9 +4231,9 @@ mod __parse__Top { // State 881 0, // State 882 - -406, - // State 883 0, + // State 883 + -408, // State 884 0, // State 885 @@ -4253,9 +4247,9 @@ mod __parse__Top { // State 889 0, // State 890 - -393, - // State 891 0, + // State 891 + -395, // State 892 0, // State 893 @@ -4269,15 +4263,15 @@ mod __parse__Top { // State 897 0, // State 898 - -824, - // State 899 0, + // State 899 + -829, // State 900 - -357, + 0, // State 901 - -861, + -359, // State 902 - 0, + -866, // State 903 0, // State 904 @@ -4287,9 +4281,9 @@ mod __parse__Top { // State 906 0, // State 907 - -827, - // State 908 0, + // State 908 + -832, // State 909 0, // State 910 @@ -4327,23 +4321,23 @@ mod __parse__Top { // State 926 0, // State 927 - -401, + -403, // State 928 - 0, + -268, // State 929 0, // State 930 - -408, + -410, // State 931 0, // State 932 - -398, + -400, // State 933 - -391, + -393, // State 934 - -265, + -405, // State 935 - -403, + 0, // State 936 0, // State 937 @@ -4367,13 +4361,13 @@ mod __parse__Top { // State 946 0, // State 947 - 0, + -426, // State 948 - -424, - // State 949 0, + // State 949 + -491, // State 950 - -488, + 0, // State 951 0, // State 952 @@ -4419,19 +4413,19 @@ mod __parse__Top { // State 972 0, // State 973 - 0, + -494, // State 974 - -491, + -859, // State 975 - -854, + -860, // State 976 - -855, + -863, // State 977 - -858, + -864, // State 978 - -859, + -358, // State 979 - -356, + 0, // State 980 0, // State 981 @@ -4445,9 +4439,9 @@ mod __parse__Top { // State 985 0, // State 986 - 0, + -893, // State 987 - -888, + 0, // State 988 0, // State 989 @@ -4469,21 +4463,21 @@ mod __parse__Top { // State 997 0, // State 998 - 0, + -402, // State 999 - -400, + -407, // State 1000 - -267, + -397, // State 1001 - -405, + 0, // State 1002 - -395, + -404, // State 1003 0, // State 1004 - -264, + 0, // State 1005 - -402, + 0, // State 1006 0, // State 1007 @@ -4493,17 +4487,17 @@ mod __parse__Top { // State 1009 0, // State 1010 - 0, + -428, // State 1011 - 0, + -105, // State 1012 - 0, + -492, // State 1013 - -426, + 0, // State 1014 - -105, + 0, // State 1015 - -489, + 0, // State 1016 0, // State 1017 @@ -4537,19 +4531,19 @@ mod __parse__Top { // State 1031 0, // State 1032 - 0, + -493, // State 1033 0, // State 1034 0, // State 1035 - -490, + -363, // State 1036 0, // State 1037 0, // State 1038 - -361, + 0, // State 1039 0, // State 1040 @@ -4571,19 +4565,19 @@ mod __parse__Top { // State 1048 0, // State 1049 - 0, + -399, // State 1050 - 0, + -406, // State 1051 - 0, + -396, // State 1052 - -397, + 0, // State 1053 - -266, + 0, // State 1054 - -404, + 0, // State 1055 - -394, + 0, // State 1056 0, // State 1057 @@ -4591,17 +4585,17 @@ mod __parse__Top { // State 1058 0, // State 1059 - 0, + -394, // State 1060 - 0, + -106, // State 1061 0, // State 1062 0, // State 1063 - -392, + 0, // State 1064 - -106, + 0, // State 1065 0, // State 1066 @@ -4651,7 +4645,7 @@ mod __parse__Top { // State 1088 0, // State 1089 - 0, + -360, // State 1090 0, // State 1091 @@ -4659,21 +4653,21 @@ mod __parse__Top { // State 1092 0, // State 1093 - -358, + 0, // State 1094 0, // State 1095 - 0, + -398, // State 1096 - 0, + -392, // State 1097 0, // State 1098 0, // State 1099 - -396, + 0, // State 1100 - -390, + 0, // State 1101 0, // State 1102 @@ -4711,19 +4705,19 @@ mod __parse__Top { // State 1118 0, // State 1119 - 0, + -858, // State 1120 - 0, + -862, // State 1121 - 0, + -364, // State 1122 0, // State 1123 - -853, + 0, // State 1124 - -857, + 0, // State 1125 - -362, + 0, // State 1126 0, // State 1127 @@ -4792,809 +4786,804 @@ mod __parse__Top { 0, // State 1159 0, - // State 1160 - 0, - // State 1161 - 0, - // State 1162 - 0, - // State 1163 - 0, ]; fn __goto(state: i16, nt: usize) -> i16 { match nt { - 11 => match state { - 238 => 887, - 275 => 937, - 276 => 938, - 311 => 1006, - 341 => 1061, - 365 => 1105, - 366 => 1106, - 374 => 1128, - _ => 820, + 9 => match state { + 242 => 888, + 278 => 936, + 279 => 937, + 312 => 1003, + 341 => 1057, + 365 => 1101, + 366 => 1102, + 374 => 1124, + _ => 824, }, - 14 => match state { - 83 => 657, - 126 => 718, - 127 => 719, - 182 => 797, - 223 => 867, - 263 => 923, - 264 => 924, - 300 => 993, - _ => 543, + 12 => match state { + 86 => 661, + 130 => 724, + 131 => 725, + 186 => 802, + 226 => 869, + 266 => 923, + 267 => 924, + 303 => 992, + _ => 544, }, - 23 => match state { - 125 => 715, - 173 => 781, - 256 => 911, - _ => 534, + 21 => match state { + 129 => 721, + 176 => 786, + 259 => 911, + _ => 535, }, - 26 => match state { - 174 => 784, - 257 => 913, - _ => 692, + 24 => match state { + 177 => 789, + 260 => 913, + _ => 698, }, - 30 => 683, + 28 => 688, + 34 => 556, 37 => 437, - 48 => 826, + 48 => 830, 52 => match state { - 63 | 96 => 103, + 66 | 99 => 106, _ => 3, }, - 55 => 66, + 55 => 69, 57 => match state { - 63 | 96 => 104, + 66 | 99 => 107, _ => 4, }, 62 => match state { - 324 => 357, + 325 => 357, _ => 356, }, 65 => match state { - 18 => 44, - 207 => 251, - 252 => 295, - _ => 153, + 19 => 46, + 211 => 255, + 256 => 298, + _ => 157, }, 70 => match state { - 63 | 96 => 598, - 286 | 321 | 324 | 344 | 346 | 348 | 351 | 354..=357 | 369 | 378 | 380 | 382 => 951, - 325 | 370 => 1023, + 66 | 99 => 601, + 289 | 322 | 325 | 344 | 346 | 348 | 351 | 354..=357 | 369 | 378 | 380 | 382 => 950, + 326 | 370 => 1020, _ => 391, }, 72 => match state { - 106 => 163, - _ => 25, + 110 => 166, + _ => 26, }, 79 => match state { - 105 => 158, - 319 | 358 => 345, - _ => 20, + 108 => 162, + 320 | 358 => 345, + _ => 21, }, 80 => match state { - 325 | 370 => 1024, - _ => 952, + 326 | 370 => 1021, + _ => 951, }, 81 => match state { - 32 => 530, - 63 | 96 => 599, - 171 => 779, + 33 => 531, + 66 | 99 => 602, + 174 => 784, _ => 392, }, - 82 => 600, + 82 => 603, 83 => match state { - 3 => 422, - 103 => 689, + 3 => 421, + 106 => 694, _ => 393, }, - 84 => 601, + 84 => 604, 85 => match state { - 136 => 730, - 159 => 768, - 187 => 804, - 193 => 810, - 225 => 870, - _ => 512, + 100 => 684, + 109 => 696, + 135 => 731, + 140 => 736, + 191 => 809, + _ => 427, }, - 86 => match state { - 30 => 72, - 63 | 96 => 105, - 166 => 211, + 87 => match state { + 31 => 75, + 66 | 99 => 108, + 169 => 215, _ => 5, }, - 87 => 602, - 88 => 953, - 89 => 479, - 90 => match state { - 90 => 668, - 133 => 727, - _ => 555, + 88 => 605, + 89 => 952, + 90 => 479, + 91 => match state { + 93 => 673, + 137 => 733, + _ => 558, }, - 92 => 90, - 94 => 394, - 95 => 603, - 96 => match state { - 14 => 463, - 63 | 96 => 604, - 113 => 699, - _ => 395, - }, - 97 => 605, - 98 => match state { - 63 | 96 => 606, - _ => 396, + 93 => 93, + 95 => 394, + 96 => 606, + 97 => match state { + 15 => 39, + 66 | 99 => 109, + 117 => 180, + _ => 6, }, - 99 => 607, - 100 => 91, - 101 => 954, - 102 => 480, - 103 => 955, - 104 => match state { - 344 => 1065, - 354 => 1082, - _ => 956, + 98 => 607, + 99 => match state { + 66 | 99 => 608, + _ => 395, }, - 107 => match state { - 37 => 541, - 41 => 547, - 42 => 549, - 67 => 633, - 172 => 780, - 176 => 789, - 177 => 790, - 178 => 792, - _ => 531, + 100 => 609, + 101 => 94, + 102 => 953, + 103 => 480, + 104 => 954, + 105 => match state { + 344 => 1061, + 354 => 1078, + _ => 955, }, - 109 => match state { - 25 | 163 => 71, - _ => 26, + 108 => match state { + 38 => 542, + 43 => 548, + 44 => 550, + 70 => 637, + 175 => 785, + 179 => 794, + 181 => 795, + 182 => 797, + _ => 532, }, - 110 => 397, - 111 => 608, - 112 => match state { - 207 => 841, - 252 => 905, - _ => 481, + 110 => match state { + 26 | 166 => 74, + _ => 27, }, + 111 => 396, + 112 => 610, 113 => match state { - 260 | 299 => 916, - _ => 860, + 211 => 845, + 256 => 906, + _ => 481, }, - 115 => match state { - 259 => 299, - _ => 260, + 114 => match state { + 263 | 302 => 916, + _ => 862, }, 116 => match state { - 63 | 96 => 609, - 286 | 321 | 323..=325 | 344..=346 | 348 | 351 | 354..=357 | 369..=370 | 378 | 380 | 382 => 957, - _ => 398, + 262 => 302, + _ => 263, }, 117 => match state { - 323 => 1020, - 345 => 1066, - _ => 958, + 66 | 99 => 611, + 289 | 322 | 324..=326 | 344..=346 | 348 | 351 | 354..=357 | 369..=370 | 378 | 380 | 382 => 956, + _ => 397, }, 118 => match state { - 325 | 370 => 358, - _ => 319, + 324 => 1017, + 345 => 1062, + _ => 957, }, 119 => match state { - 45 => 553, - _ => 482, + 326 | 370 => 358, + _ => 320, }, - 121 => 45, - 122 => 483, - 123 => match state { - 85 => 662, - _ => 471, + 120 => match state { + 47 => 554, + _ => 482, }, + 122 => 47, + 123 => 483, 124 => match state { - 115 => 177, - 85 => 663, - _ => 41, + 88 => 666, + _ => 471, }, 125 => match state { - 115 => 701, + 119 => 181, + 88 => 667, + _ => 43, + }, + 126 => match state { + 119 => 706, _ => 472, }, - 127 => match state { - 56 => 589, - 99 => 681, - 149 => 752, - _ => 581, + 128 => match state { + 59 => 592, + 102 => 686, + 153 => 758, + _ => 584, }, - 128 => 822, - 130 => match state { - 204 => 833, - _ => 763, + 129 => 826, + 131 => match state { + 208 => 837, + _ => 769, }, - 131 => 204, - 132 => match state { - 205 => 836, - _ => 764, + 132 => 208, + 133 => match state { + 209 => 840, + _ => 770, }, - 133 => 205, - 134 => match state { - 63 | 96 => 106, - 12 => 455, - 26 => 522, - 35 => 538, - 43 => 551, - 51..=52 | 75 | 95 | 123 | 141 | 143 => 573, - 71 => 638, - 168 => 775, - 175 => 787, - 215 => 853, - 254 => 909, - _ => 6, + 134 => 209, + 135 => match state { + 19 | 46 | 104 | 141 | 151 | 157 | 160 | 173 | 192 | 196..=198 | 202 | 211 | 228..=229 | 231 | 233..=234 | 238 | 244 | 253..=256 | 270..=271 | 273 | 275..=277 | 286 | 292..=296 | 298..=299 | 308..=311 | 317..=318 | 328 | 335..=337 | 342..=343 | 352 | 360 | 362..=363 | 368 | 371..=373 => 48, + 66 | 99 => 110, + 13 => 456, + 27 => 523, + 36 => 539, + 45 => 552, + 54..=55 | 78 | 98 | 127 | 145 | 147 => 576, + 74 => 642, + 171 => 780, + 178 => 792, + _ => 7, }, - 135 => 610, - 136 => match state { - 75 => 642, - 95 => 677, - 123 => 712, - _ => 578, + 136 => 612, + 137 => match state { + 78 => 646, + 98 => 682, + 127 => 718, + _ => 581, }, - 137 => 574, - 138 => 917, - 139 => match state { - 141 | 143 => 743, - _ => 575, + 138 => 577, + 139 => 917, + 140 => match state { + 145 | 147 => 749, + _ => 578, }, - 140 => 484, - 141 => match state { - 10 => 447, - 24 => 521, - 31 => 529, - 109 => 691, - 162 => 771, - 167 => 774, - _ => 399, + 141 => 484, + 142 => match state { + 11 => 447, + 25 => 522, + 32 => 530, + 113 => 697, + 165 => 776, + 170 => 779, + _ => 398, }, - 142 => 611, - 143 => 485, - 144 => 486, - 145 => 487, - 146 => match state { - 66 => 630, + 143 => 613, + 144 => 485, + 145 => 486, + 146 => 487, + 147 => match state { + 69 => 633, _ => 513, }, - 148 => 579, - 149 => match state { - 1 => 7, - 36 => 539, - 60 => 595, - 91..=92 => 669, - 142 => 744, - 191 => 808, - _ => 46, - }, - 150 => 488, - 151 => 1016, - 152 => match state { - 49 => 97, - 50 => 98, - 88 => 131, - 89 => 132, - 94 => 135, - 130 => 186, - 11 | 13 | 17 | 23 | 47 | 55 | 57 | 62 | 76..=77 | 79 | 86 | 111..=112 | 115 | 117 | 119 | 124 | 150..=151 | 161 | 181 | 213..=214 | 219 | 243 | 255 | 282 | 297 | 329 | 353 => 448, - 15 | 80 | 84 | 128..=129 | 183..=185 | 220..=222 | 262 | 265 | 301..=303 | 331..=333 | 361 => 464, - 21 | 66 | 136 | 159 | 187 | 193 | 225 => 514, - 22 => 515, - 38..=39 | 126 | 223 | 263 => 544, - 54 | 58 => 586, - 61 => 596, - 63 | 96 => 612, - 138 | 232 => 732, - 140 | 236 | 239 | 277 | 279 | 312..=314 | 338..=340 | 364 | 367 | 375..=377 | 384..=387 => 736, - 144 | 201 => 745, - 145 => 749, + 149 => 582, + 150 => match state { + 1 => 8, + 37 => 540, + 63 => 598, + 94..=95 => 674, 146 => 750, - 148 => 751, - 160 => 769, - 195 => 814, - 196 => 815, - 199 | 275 | 341 | 365 => 821, - 200 => 823, - 202 => 825, - 241 => 891, - 242 | 281 => 892, - 244 => 896, - 286 | 321 | 324 | 344 | 351 | 354..=357 | 369 | 378 => 959, - 294 => 980, - 315 => 1012, - 322 => 1019, - 325 | 370 => 1025, - 328 => 1039, - 346 | 348 | 380 | 382 => 1067, - 347 => 1073, - 349 => 1077, - 350 => 1078, - 359 => 1092, - 379 | 381 | 388..=389 => 1134, - 383 => 1144, - _ => 400, - }, - 153 => 489, - 156 => 746, - 157 => match state { - 99 => 682, - _ => 582, + 195 => 813, + _ => 49, }, - 159 => 99, - 160 => 583, - 161 => 490, - 162 => match state { - 236 => 884, - 239 => 888, - 277 => 939, - 279 => 942, - 312 => 1007, - 313 => 1008, - 314 => 1010, - 338 => 1056, - 339 => 1057, - 340 => 1059, - 364 => 1102, - 367 => 1107, - 375 => 1129, - 376 => 1130, - 377 => 1131, - 384 => 1146, - 385 => 1147, - 386 => 1150, - 387 => 1157, - _ => 737, + 151 => 488, + 152 => 1013, + 153 => match state { + 52 => 100, + 53 => 101, + 91 => 135, + 92 => 136, + 97 => 139, + 134 => 190, + 12 | 14 | 18 | 24 | 50 | 58 | 60 | 65 | 79..=80 | 82 | 89 | 115..=116 | 119 | 121 | 123 | 128 | 154..=155 | 164 | 185 | 217..=218 | 222 | 247 | 258 | 285 | 300 | 330 | 353 => 448, + 16 | 83 | 87 | 132..=133 | 187..=189 | 223..=225 | 265 | 268 | 304..=306 | 332..=334 | 361 => 464, + 22 | 69 => 514, + 23 => 516, + 40..=41 | 130 | 226 | 266 => 545, + 57 | 61 => 589, + 64 => 599, + 66 | 99 => 614, + 142 | 236 => 738, + 144 | 240 | 243 | 280 | 282 | 313..=315 | 338..=340 | 364 | 367 | 375..=377 | 384..=387 => 742, + 148 | 205 => 751, + 149 => 755, + 150 => 756, + 152 => 757, + 163 => 774, + 199 => 818, + 200 => 819, + 203 | 278 | 341 | 365 => 825, + 204 => 827, + 206 => 829, + 245 => 892, + 246 | 284 => 893, + 248 => 897, + 289 | 322 | 325 | 344 | 351 | 354..=357 | 369 | 378 => 958, + 297 => 979, + 316 => 1009, + 323 => 1016, + 326 | 370 => 1022, + 329 => 1036, + 346 | 348 | 380 | 382 => 1063, + 347 => 1069, + 349 => 1073, + 350 => 1074, + 359 => 1088, + 379 | 381 | 388..=389 => 1130, + 383 => 1140, + _ => 399, }, - 163 => match state { - 80 => 653, - 84 => 658, - 128 => 720, - 129 => 722, - 183 => 798, - 184 => 799, - 185 => 801, - 220 => 862, - 221 => 863, - 222 => 865, - 262 => 920, - 265 => 925, - 301 => 994, - 302 => 995, - 303 => 996, - 331 => 1046, - 332 => 1047, - 333 => 1050, - 361 => 1096, - _ => 465, + 154 => 489, + 157 => 752, + 158 => match state { + 102 => 687, + _ => 585, }, - 164 => match state { - 63 | 96 => 613, - _ => 401, + 160 => 102, + 161 => 586, + 162 => 490, + 163 => 677, + 164 => 491, + 165 => 492, + 166 => match state { + 240 => 885, + 243 => 889, + 280 => 938, + 282 => 941, + 313 => 1004, + 314 => 1005, + 315 => 1007, + 338 => 1052, + 339 => 1053, + 340 => 1055, + 364 => 1098, + 367 => 1103, + 375 => 1125, + 376 => 1126, + 377 => 1127, + 384 => 1142, + 385 => 1143, + 386 => 1146, + 387 => 1153, + _ => 743, }, - 165 => 672, - 166 => 491, 167 => match state { - 112 => 697, - _ => 456, + 83 => 657, + 87 => 662, + 132 => 726, + 133 => 728, + 187 => 803, + 188 => 804, + 189 => 806, + 223 => 864, + 224 => 865, + 225 => 867, + 265 => 920, + 268 => 925, + 304 => 993, + 305 => 994, + 306 => 995, + 332 => 1043, + 333 => 1044, + 334 => 1047, + 361 => 1092, + _ => 465, }, - 169 => 960, - 170 => 1026, - 171 => 961, - 172 => match state { - 245..=246 | 284 | 287 => 897, - _ => 949, + 168 => match state { + 66 | 99 => 615, + _ => 400, }, - 173 => match state { - 246 => 288, - 284 => 318, - 287 => 326, - _ => 285, + 169 => match state { + 116 => 703, + _ => 457, }, + 171 => 959, + 172 => 1023, + 173 => 960, 174 => match state { - 379 | 381 | 388..=389 => 1135, - _ => 1068, + 249..=250 | 287 | 290 => 898, + _ => 948, }, 175 => match state { - 370 => 1119, - _ => 1027, + 250 => 291, + 287 => 319, + 290 => 327, + _ => 288, }, 176 => match state { - 325 | 370 => 1028, - _ => 962, + 379 | 381 | 388..=389 => 1131, + _ => 1064, }, 177 => match state { - 325 | 370 => 1029, - _ => 963, + 370 => 1115, + _ => 1024, }, - 178 => 492, - 179 => match state { - 108 => 167, - _ => 31, + 178 => match state { + 326 | 370 => 1025, + _ => 961, }, - 180 => match state { - 11 | 111 => 449, - 77 | 214 => 646, - _ => 457, + 179 => match state { + 326 | 370 => 1026, + _ => 962, }, + 180 => 493, 181 => match state { - 11 => 33, - 17 => 42, - 21 | 66 | 136 | 159 | 187 | 193 | 225 => 67, - 111 => 172, - 115 => 178, - 47 => 571, - 55 => 588, - 62 => 597, - 243 => 895, - 282 => 947, - 353 => 1081, - _ => 458, + 112 => 170, + _ => 32, }, 182 => match state { - 77 => 125, - 111 => 173, - 214 => 256, - _ => 34, + 12 | 115 => 449, + 80 | 218 => 650, + _ => 458, }, - 183 => 493, + 183 => 450, 184 => match state { - 4 => 423, - 16 => 470, - 104 => 690, - 114 => 700, - _ => 402, + 12 => 34, + 18 => 44, + 22 | 69 => 70, + 115 => 175, + 119 => 182, + 50 => 574, + 58 => 591, + 65 => 600, + 247 => 896, + 285 => 946, + 353 => 1077, + _ => 459, }, - 185 => 614, - 186 => 473, - 187 => match state { - 51 => 576, - _ => 580, + 185 => match state { + 80 => 129, + 115 => 176, + 218 => 259, + _ => 35, }, - 188 => match state { - 58 => 593, - _ => 587, + 186 => 494, + 187 => match state { + 4 => 422, + 17 => 470, + 107 => 695, + 118 => 705, + _ => 401, }, - 189 => 590, + 188 => 616, + 189 => 473, 190 => match state { - 201 => 824, - _ => 747, + 54 => 579, + _ => 583, }, 191 => match state { - 348 => 1074, - 380 => 1137, - 382 => 1141, - _ => 1069, + 61 => 596, + _ => 590, }, - 192 => 1030, - 193 => 738, - 194 => 466, - 195 => match state { - 348 => 1075, - _ => 1070, + 192 => 593, + 193 => match state { + 205 => 828, + _ => 753, }, - 196 => match state { - 111 => 693, - _ => 450, + 194 => match state { + 348 => 1070, + 380 => 1133, + 382 => 1137, + _ => 1065, }, - 197 => 403, + 195 => 1027, + 196 => 744, + 197 => 466, 198 => match state { - 17 | 115 => 474, - _ => 459, + 348 => 1071, + _ => 1066, }, - 199 => 733, - 200 => 964, - 201 => match state { - 180 => 218, - 217 => 259, - 29 => 528, - 63 | 96 => 615, - 165 => 773, - 261 => 918, - _ => 404, + 199 => match state { + 115 => 699, + _ => 451, }, - 202 => 616, - 203 => match state { - 140 => 739, - 236 => 885, - 277 | 314 | 338 | 340 | 364 | 376 | 384 | 386..=387 => 940, - _ => 889, + 200 => 402, + 201 => match state { + 18 | 119 => 474, + _ => 460, }, + 202 => 739, + 203 => 963, 204 => match state { - 15 => 467, - 80 => 654, - 84 | 129 | 183..=184 | 221 | 265 | 301 | 303 | 332 => 659, - _ => 721, + 184 => 221, + 220 => 262, + 30 => 529, + 66 | 99 => 617, + 168 => 778, + 264 => 918, + _ => 403, }, - 207 => 740, - 208 => 468, - 212 => match state { - 132 => 726, - 135 => 729, - 139 => 735, - 186 => 803, - 189 => 806, - 190 => 807, - 224 => 869, - _ => 680, + 205 => 618, + 206 => match state { + 144 => 745, + 240 => 886, + 280 | 315 | 338 | 340 | 364 | 376 | 384 | 386..=387 => 939, + _ => 890, }, - 213 => 494, - 214 => match state { - 286 => 965, - 321 => 1017, - 324 => 1021, - 351 => 1079, - 355 => 1083, - 356 => 1084, - 357 => 1087, - 369 => 1118, - 378 => 1133, - 380 | 382 => 1138, - _ => 1071, + 207 => match state { + 16 => 467, + 83 => 658, + 87 | 133 | 187..=188 | 224 | 268 | 304 | 306 | 333 => 663, + _ => 727, }, - 216 => 320, - 217 => 405, - 218 => 617, - 219 => 18, - 220 => 495, - 221 => 966, - 222 => match state { - 115 => 702, - _ => 475, + 210 => 746, + 211 => 468, + 215 => match state { + 136 => 732, + 139 => 735, + 143 => 741, + 190 => 808, + 193 => 811, + 194 => 812, + 227 => 871, + _ => 685, }, - 223 => match state { - 19 => 64, - 63 | 96 => 107, - 157 => 209, - _ => 8, + 216 => 495, + 217 => match state { + 289 => 964, + 322 => 1014, + 325 => 1018, + 351 => 1075, + 355 => 1079, + 356 => 1080, + 357 => 1083, + 369 => 1114, + 378 => 1129, + 380 | 382 => 1134, + _ => 1067, }, - 224 => 618, + 219 => 321, + 220 => 404, + 221 => 619, + 222 => 19, + 223 => 496, + 224 => 965, 225 => match state { - 107 => 166, - _ => 30, + 119 => 707, + _ => 475, }, 226 => match state { - 74 => 641, - _ => 532, + 20 => 67, + 66 | 99 => 111, + 161 => 213, + _ => 9, }, - 227 => 74, + 227 => 620, 228 => match state { - 118 => 707, - 120 => 709, - 179 => 794, - _ => 637, + 111 => 169, + _ => 31, }, - 230 => match state { - 18 => 496, - 44 => 552, - 153 => 760, - 207 => 842, - 251 => 902, - 252 => 906, - 295 => 984, - _ => 686, + 229 => match state { + 77 => 645, + _ => 533, }, + 230 => 77, 231 => match state { - 11 | 77 | 111 | 214 => 451, - 13 | 17 | 23 | 57 | 76 | 79 | 86 | 112 | 115 | 117 | 119 | 124 | 150..=151 | 161 | 181 | 213 | 219 | 255 | 297 | 329 => 460, - 51..=52 | 75 | 95 | 123 | 141 | 143 => 577, - _ => 406, + 122 => 713, + 124 => 715, + 183 => 799, + _ => 641, }, - 232 => 967, 233 => match state { - 275 => 311, + 19 => 497, + 46 => 553, + 157 => 766, + 211 => 846, + 255 => 903, + 256 => 907, + 298 => 983, + _ => 691, + }, + 234 => match state { + 12 | 80 | 115 | 218 => 452, + 14 | 18 | 24 | 60 | 79 | 82 | 89 | 116 | 119 | 121 | 123 | 128 | 154..=155 | 164 | 185 | 217 | 222 | 258 | 300 | 330 => 461, + 54..=55 | 78 | 98 | 127 | 145 | 147 => 580, + _ => 405, + }, + 235 => 966, + 236 => match state { + 278 => 312, 341 => 366, 365 => 374, - _ => 238, - }, - 235 => match state { - 126 => 182, - 223 => 264, - 263 => 300, - 39 => 545, - _ => 83, + _ => 242, }, - 237 => 252, 238 => match state { - 117 => 706, - 119 => 708, - _ => 516, + 130 => 186, + 226 => 267, + 266 => 303, + 41 => 546, + _ => 86, }, - 239 => match state { - 161 => 770, + 240 => 256, + 241 => match state { + 121 => 712, + 123 => 714, _ => 517, }, - 240 => match state { - 147 => 203, - 137 => 731, - 156 => 767, - 170 => 778, - 188 => 805, - 192 => 809, - 194 => 811, - 198 => 817, - 226 => 871, - 228 => 874, - 230 => 876, - 234 => 882, - 240 => 890, - 249 => 900, - 250 => 901, - 267 => 927, - 269 => 930, - 271 => 932, - 272 => 933, - 273 => 934, - 274 => 935, - 283 => 948, - 289 => 975, - 290 => 976, - 291 => 977, - 292 => 978, - 293 => 979, - 296 => 987, - 305 => 999, - 306 => 1000, - 307 => 1001, - 308 => 1002, - 309 => 1004, - 310 => 1005, - 316 => 1013, - 317 => 1014, - 327 => 1038, - 334 => 1052, - 335 => 1053, - 336 => 1054, - 337 => 1055, - 342 => 1063, - 343 => 1064, - 352 => 1080, - 360 => 1093, - 362 => 1099, - 363 => 1100, - 368 => 1112, - 371 => 1123, - 372 => 1124, - 373 => 1125, - _ => 154, - }, - 241 => match state { - 20 => 65, - 63 | 96 => 108, - 158 => 210, - _ => 9, + 242 => match state { + 164 => 775, + _ => 518, }, - 242 => 619, 243 => match state { - 70 => 120, - 93 => 133, - 118 => 179, - 1 | 28 | 36 | 60 | 91..=92 | 142 | 191 | 278 => 407, - 11 => 452, - 13 | 21 | 47 | 55 | 57 | 62 | 66 | 76 | 79 | 86 | 112 | 124 | 136 | 150..=151 | 159 | 181 | 187 | 193 | 213 | 219 | 225 | 243 | 255 | 282 | 297 | 329 | 353 => 461, - 17 | 115 => 476, - 23 | 117 | 119 | 161 => 518, - 40 => 546, - 48 => 572, - 59 => 594, - 63 | 96 => 620, - 68 => 634, - 69 => 635, - 73 => 639, - 77 => 647, - 78 => 650, - 81 => 655, - 82 => 656, - 85 => 664, - 87 => 665, - 111 => 694, - 116 => 705, - 121 => 710, - 122 => 711, - 134 => 728, - 152 => 759, - 155 => 766, - 169 | 212 | 216 | 258 | 298 | 330 => 776, - 197 => 816, - 206 | 247 => 840, - 208 => 843, - 214 => 851, - 227 => 873, - 229 => 875, - 231 => 878, - 233 => 881, - 235 => 883, - 237 => 886, - 248 => 899, - 253 => 908, - 266 => 926, - 268 => 929, - 270 => 931, - 280 => 944, - 304 => 998, - _ => 497, + 151 => 207, + 141 => 737, + 160 => 773, + 173 => 783, + 192 => 810, + 196 => 814, + 197 => 815, + 198 => 816, + 202 => 821, + 228 => 872, + 229 => 873, + 231 => 875, + 233 => 877, + 234 => 878, + 238 => 883, + 244 => 891, + 253 => 901, + 254 => 902, + 270 => 927, + 271 => 928, + 273 => 930, + 275 => 932, + 276 => 933, + 277 => 934, + 286 => 947, + 292 => 974, + 293 => 975, + 294 => 976, + 295 => 977, + 296 => 978, + 299 => 986, + 308 => 998, + 309 => 999, + 310 => 1000, + 311 => 1002, + 317 => 1010, + 318 => 1011, + 328 => 1035, + 335 => 1049, + 336 => 1050, + 337 => 1051, + 342 => 1059, + 343 => 1060, + 352 => 1076, + 360 => 1089, + 362 => 1095, + 363 => 1096, + 368 => 1108, + 371 => 1119, + 372 => 1120, + 373 => 1121, + _ => 158, }, - 245 => 621, - 248 => match state { - 92 => 673, - _ => 670, + 244 => match state { + 21 => 68, + 66 | 99 => 112, + 162 => 214, + _ => 10, }, - 249 => match state { - 28 => 527, - 278 => 941, - _ => 408, + 245 => 621, + 246 => match state { + 73 => 124, + 96 => 137, + 122 => 183, + 1 | 29 | 37 | 63 | 94..=95 | 146 | 195 | 281 => 406, + 12 => 453, + 14 | 22 | 50 | 58 | 60 | 65 | 69 | 79 | 82 | 89 | 116 | 128 | 154..=155 | 185 | 217 | 222 | 247 | 258 | 285 | 300 | 330 | 353 => 462, + 18 | 119 => 476, + 24 | 121 | 123 | 164 => 519, + 42 => 547, + 51 => 575, + 62 => 597, + 66 | 99 | 172 | 216 | 219 | 261 | 301 | 331 => 622, + 71 => 638, + 72 => 639, + 76 => 643, + 80 => 651, + 81 => 654, + 84 => 659, + 85 => 660, + 88 => 668, + 90 => 669, + 115 => 700, + 120 => 711, + 125 => 716, + 126 => 717, + 138 => 734, + 156 => 765, + 159 => 772, + 201 => 820, + 210 | 251 => 844, + 212 => 847, + 218 => 854, + 230 => 874, + 232 => 876, + 235 => 879, + 237 => 882, + 239 => 884, + 241 => 887, + 252 => 900, + 257 => 909, + 269 => 926, + 272 => 929, + 274 => 931, + 283 => 943, + 307 => 997, + _ => 498, }, + 248 => 623, 251 => match state { - 13 => 37, - 112 => 176, - 17 | 115 => 477, - 57 => 591, - 76 | 181 | 213 | 297 => 644, - 79 | 86 => 651, - 124 | 219 | 255 | 329 => 713, - 150 => 753, - 151 => 756, - _ => 519, + 95 => 678, + _ => 675, }, - 252 => 390, - 253 => 498, - 254 => 968, - 255 => 969, - 256 => 520, - 257 => 592, - 258 => 102, - 259 => 499, - 260 => match state { - 232 => 879, - _ => 734, + 252 => match state { + 29 => 528, + 281 => 940, + _ => 407, }, - 261 => match state { - 132 => 189, - 135 => 190, - 186 => 224, - 97 => 679, - 102 => 688, - 131 => 725, - _ => 139, + 254 => match state { + 14 => 38, + 116 => 179, + 18 | 119 => 477, + 60 => 594, + 79 | 185 | 217 | 300 => 648, + 82 | 89 => 655, + 128 | 222 | 258 | 330 => 719, + 154 => 759, + 155 => 762, + _ => 520, }, - 263 => 741, - 264 => match state { - 63 | 96 => 109, - _ => 10, + 255 => 390, + 256 => 499, + 257 => 967, + 258 => 968, + 259 => 521, + 260 => 595, + 261 => 105, + 262 => 500, + 263 => match state { + 236 => 880, + _ => 740, }, - 265 => 469, - 266 => 970, - 267 => 500, - 268 => match state { - 63 | 96 => 110, - 212 | 258 | 330 => 847, - _ => 777, + 264 => match state { + 101 => 143, + 135 => 191, + 136 => 193, + 139 => 194, + 190 => 227, + 105 => 693, + _ => 140, }, - 269 => match state { - 214 => 257, - _ => 174, + 266 => 747, + 267 => match state { + 66 | 99 => 113, + _ => 11, }, - 270 => 622, + 268 => 469, + 269 => 969, + 270 => 501, 271 => match state { - 96 => 678, - _ => 623, + 66 | 99 => 114, + 216 | 261 | 331 => 850, + _ => 781, + }, + 272 => 624, + 273 => match state { + 115 => 177, + 218 => 260, + 66 | 99 => 625, + _ => 782, }, - 273 => 501, 274 => match state { - 27 => 525, - 63 | 96 => 624, - 164 => 772, - _ => 409, + 99 => 683, + _ => 626, + }, + 276 => 502, + 277 => match state { + 28 => 526, + 66 | 99 => 627, + 167 => 777, + _ => 408, }, - 275 => 625, - 276 => match state { - 11 => 453, - 91..=92 => 671, - 111 => 695, - _ => 502, + 278 => 628, + 279 => match state { + 12 => 454, + 94..=95 => 676, + 115 => 701, + _ => 503, }, _ => 0, } @@ -5637,6 +5626,7 @@ mod __parse__Top { r###"">=""###, r###"">>""###, r###"">>=""###, + r###""?""###, r###""@""###, r###""@=""###, r###""False""###, @@ -5693,7 +5683,7 @@ mod __parse__Top { r###"complex"###, r###"float"###, r###"int"###, - r###"line_magic"###, + r###"ipy_escape_command"###, r###"name"###, r###"string"###, ]; @@ -5763,7 +5753,7 @@ mod __parse__Top { #[inline] fn error_action(&self, state: i16) -> i16 { - __action(state, 96 - 1) + __action(state, 97 - 1) } #[inline] @@ -5866,65 +5856,66 @@ mod __parse__Top { token::Tok::GreaterEqual if true => Some(34), token::Tok::RightShift if true => Some(35), token::Tok::RightShiftEqual if true => Some(36), - token::Tok::At if true => Some(37), - token::Tok::AtEqual if true => Some(38), - token::Tok::False if true => Some(39), - token::Tok::None if true => Some(40), - token::Tok::True if true => Some(41), - token::Tok::Lsqb if true => Some(42), - token::Tok::Rsqb if true => Some(43), - token::Tok::CircumFlex if true => Some(44), - token::Tok::CircumflexEqual if true => Some(45), - token::Tok::And if true => Some(46), - token::Tok::As if true => Some(47), - token::Tok::Assert if true => Some(48), - token::Tok::Async if true => Some(49), - token::Tok::Await if true => Some(50), - token::Tok::Break if true => Some(51), - token::Tok::Case if true => Some(52), - token::Tok::Class if true => Some(53), - token::Tok::Continue if true => Some(54), - token::Tok::Def if true => Some(55), - token::Tok::Del if true => Some(56), - token::Tok::Elif if true => Some(57), - token::Tok::Else if true => Some(58), - token::Tok::Except if true => Some(59), - token::Tok::Finally if true => Some(60), - token::Tok::For if true => Some(61), - token::Tok::From if true => Some(62), - token::Tok::Global if true => Some(63), - token::Tok::If if true => Some(64), - token::Tok::Import if true => Some(65), - token::Tok::In if true => Some(66), - token::Tok::Is if true => Some(67), - token::Tok::Lambda if true => Some(68), - token::Tok::Match if true => Some(69), - token::Tok::Nonlocal if true => Some(70), - token::Tok::Not if true => Some(71), - token::Tok::Or if true => Some(72), - token::Tok::Pass if true => Some(73), - token::Tok::Raise if true => Some(74), - token::Tok::Return if true => Some(75), - token::Tok::Try if true => Some(76), - token::Tok::Type if true => Some(77), - token::Tok::While if true => Some(78), - token::Tok::With if true => Some(79), - token::Tok::Yield if true => Some(80), - token::Tok::Lbrace if true => Some(81), - token::Tok::Vbar if true => Some(82), - token::Tok::VbarEqual if true => Some(83), - token::Tok::Rbrace if true => Some(84), - token::Tok::Tilde if true => Some(85), - token::Tok::Dedent if true => Some(86), - token::Tok::Indent if true => Some(87), - token::Tok::StartExpression if true => Some(88), - token::Tok::StartModule if true => Some(89), - token::Tok::Complex { real: _, imag: _ } if true => Some(90), - token::Tok::Float { value: _ } if true => Some(91), - token::Tok::Int { value: _ } if true => Some(92), - token::Tok::MagicCommand { kind: _, value: _ } if true => Some(93), - token::Tok::Name { name: _ } if true => Some(94), - token::Tok::String { value: _, kind: _, triple_quoted: _ } if true => Some(95), + token::Tok::Question if true => Some(37), + token::Tok::At if true => Some(38), + token::Tok::AtEqual if true => Some(39), + token::Tok::False if true => Some(40), + token::Tok::None if true => Some(41), + token::Tok::True if true => Some(42), + token::Tok::Lsqb if true => Some(43), + token::Tok::Rsqb if true => Some(44), + token::Tok::CircumFlex if true => Some(45), + token::Tok::CircumflexEqual if true => Some(46), + token::Tok::And if true => Some(47), + token::Tok::As if true => Some(48), + token::Tok::Assert if true => Some(49), + token::Tok::Async if true => Some(50), + token::Tok::Await if true => Some(51), + token::Tok::Break if true => Some(52), + token::Tok::Case if true => Some(53), + token::Tok::Class if true => Some(54), + token::Tok::Continue if true => Some(55), + token::Tok::Def if true => Some(56), + token::Tok::Del if true => Some(57), + token::Tok::Elif if true => Some(58), + token::Tok::Else if true => Some(59), + token::Tok::Except if true => Some(60), + token::Tok::Finally if true => Some(61), + token::Tok::For if true => Some(62), + token::Tok::From if true => Some(63), + token::Tok::Global if true => Some(64), + token::Tok::If if true => Some(65), + token::Tok::Import if true => Some(66), + token::Tok::In if true => Some(67), + token::Tok::Is if true => Some(68), + token::Tok::Lambda if true => Some(69), + token::Tok::Match if true => Some(70), + token::Tok::Nonlocal if true => Some(71), + token::Tok::Not if true => Some(72), + token::Tok::Or if true => Some(73), + token::Tok::Pass if true => Some(74), + token::Tok::Raise if true => Some(75), + token::Tok::Return if true => Some(76), + token::Tok::Try if true => Some(77), + token::Tok::Type if true => Some(78), + token::Tok::While if true => Some(79), + token::Tok::With if true => Some(80), + token::Tok::Yield if true => Some(81), + token::Tok::Lbrace if true => Some(82), + token::Tok::Vbar if true => Some(83), + token::Tok::VbarEqual if true => Some(84), + token::Tok::Rbrace if true => Some(85), + token::Tok::Tilde if true => Some(86), + token::Tok::Dedent if true => Some(87), + token::Tok::Indent if true => Some(88), + token::Tok::StartExpression if true => Some(89), + token::Tok::StartModule if true => Some(90), + token::Tok::Complex { real: _, imag: _ } if true => Some(91), + token::Tok::Float { value: _ } if true => Some(92), + token::Tok::Int { value: _ } if true => Some(93), + token::Tok::IpyEscapeCommand { kind: _, value: _ } if true => Some(94), + token::Tok::Name { name: _ } if true => Some(95), + token::Tok::String { value: _, kind: _, triple_quoted: _ } if true => Some(96), _ => None, } } @@ -5936,28 +5927,28 @@ mod __parse__Top { ) -> __Symbol<> { match __token_index { - 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 => __Symbol::Variant0(__token), - 90 => match __token { + 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 => __Symbol::Variant0(__token), + 91 => match __token { token::Tok::Complex { real: __tok0, imag: __tok1 } if true => __Symbol::Variant1((__tok0, __tok1)), _ => unreachable!(), }, - 91 => match __token { + 92 => match __token { token::Tok::Float { value: __tok0 } if true => __Symbol::Variant2(__tok0), _ => unreachable!(), }, - 92 => match __token { + 93 => match __token { token::Tok::Int { value: __tok0 } if true => __Symbol::Variant3(__tok0), _ => unreachable!(), }, - 93 => match __token { - token::Tok::MagicCommand { kind: __tok0, value: __tok1 } if true => __Symbol::Variant4((__tok0, __tok1)), + 94 => match __token { + token::Tok::IpyEscapeCommand { kind: __tok0, value: __tok1 } if true => __Symbol::Variant4((__tok0, __tok1)), _ => unreachable!(), }, - 94 => match __token { + 95 => match __token { token::Tok::Name { name: __tok0 } if true => __Symbol::Variant5(__tok0), _ => unreachable!(), }, - 95 => match __token { + 96 => match __token { token::Tok::String { value: __tok0, kind: __tok1, triple_quoted: __tok2 } if true => __Symbol::Variant6((__tok0, __tok1, __tok2)), _ => unreachable!(), }, @@ -6009,13 +6000,13 @@ mod __parse__Top { } 6 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 2, nonterminal_produced: 3, } } 7 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 2, nonterminal_produced: 4, } } @@ -6051,13 +6042,13 @@ mod __parse__Top { } 13 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 0, nonterminal_produced: 8, } } 14 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 8, } } @@ -6069,25 +6060,25 @@ mod __parse__Top { } 16 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 10, + states_to_pop: 3, + nonterminal_produced: 9, } } 17 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 10, } } 18 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 0, nonterminal_produced: 11, } } 19 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 11, } } @@ -6099,223 +6090,223 @@ mod __parse__Top { } 21 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 13, + states_to_pop: 3, + nonterminal_produced: 12, } } 22 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 5, nonterminal_produced: 13, } } 23 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 14, + states_to_pop: 4, + nonterminal_produced: 13, } } 24 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 14, + states_to_pop: 6, + nonterminal_produced: 13, } } 25 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 15, + nonterminal_produced: 13, } } 26 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 15, + states_to_pop: 3, + nonterminal_produced: 13, } } 27 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 15, + states_to_pop: 2, + nonterminal_produced: 13, } } 28 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 15, + states_to_pop: 4, + nonterminal_produced: 13, } } 29 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 15, + nonterminal_produced: 13, } } 30 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 15, + states_to_pop: 5, + nonterminal_produced: 14, } } 31 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 15, + nonterminal_produced: 14, } } 32 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 15, + states_to_pop: 6, + nonterminal_produced: 14, } } 33 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 16, + nonterminal_produced: 14, } } 34 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 16, + states_to_pop: 3, + nonterminal_produced: 14, } } 35 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 16, + states_to_pop: 2, + nonterminal_produced: 14, } } 36 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 16, + states_to_pop: 4, + nonterminal_produced: 14, } } 37 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 16, + nonterminal_produced: 14, } } 38 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 16, + states_to_pop: 0, + nonterminal_produced: 14, } } 39 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 16, + states_to_pop: 5, + nonterminal_produced: 15, } } 40 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 16, + states_to_pop: 4, + nonterminal_produced: 15, } } 41 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 16, + states_to_pop: 6, + nonterminal_produced: 15, } } 42 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 17, + nonterminal_produced: 15, } } 43 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 17, + states_to_pop: 3, + nonterminal_produced: 15, } } 44 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 17, + states_to_pop: 2, + nonterminal_produced: 15, } } 45 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 17, + states_to_pop: 4, + nonterminal_produced: 15, } } 46 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 17, + nonterminal_produced: 15, } } 47 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 17, + states_to_pop: 5, + nonterminal_produced: 16, } } 48 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 17, + nonterminal_produced: 16, } } 49 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 17, + states_to_pop: 6, + nonterminal_produced: 16, } } 50 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 18, + nonterminal_produced: 16, } } 51 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 18, + states_to_pop: 3, + nonterminal_produced: 16, } } 52 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 18, + states_to_pop: 2, + nonterminal_produced: 16, } } 53 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 18, + states_to_pop: 4, + nonterminal_produced: 16, } } 54 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 18, + nonterminal_produced: 16, } } 55 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 18, + states_to_pop: 0, + nonterminal_produced: 16, } } 56 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 18, + states_to_pop: 2, + nonterminal_produced: 17, } } 57 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 2, nonterminal_produced: 18, } } @@ -6333,13 +6324,13 @@ mod __parse__Top { } 60 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 0, nonterminal_produced: 20, } } 61 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 20, } } @@ -6351,25 +6342,25 @@ mod __parse__Top { } 63 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 22, + states_to_pop: 3, + nonterminal_produced: 21, } } 64 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 22, } } 65 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 0, nonterminal_produced: 23, } } 66 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 23, } } @@ -6381,13 +6372,13 @@ mod __parse__Top { } 68 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 25, + states_to_pop: 3, + nonterminal_produced: 24, } } 69 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 25, } } @@ -6399,7 +6390,7 @@ mod __parse__Top { } 71 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 0, nonterminal_produced: 26, } } @@ -6417,7 +6408,7 @@ mod __parse__Top { } 74 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 3, nonterminal_produced: 28, } } @@ -6435,7 +6426,7 @@ mod __parse__Top { } 77 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 0, nonterminal_produced: 30, } } @@ -6459,19 +6450,19 @@ mod __parse__Top { } 81 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 33, } } 82 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 34, } } 83 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 34, } } @@ -6945,37 +6936,37 @@ mod __parse__Top { } 162 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 85, } } 163 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 85, } } 164 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 4, nonterminal_produced: 85, } } 165 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 85, } } 166 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 86, } } 167 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 86, } } @@ -6999,19 +6990,19 @@ mod __parse__Top { } 171 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 89, + states_to_pop: 1, + nonterminal_produced: 88, } } 172 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 3, nonterminal_produced: 89, } } 173 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 4, nonterminal_produced: 90, } } @@ -7023,25 +7014,25 @@ mod __parse__Top { } 175 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 91, } } 176 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 91, } } 177 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 92, } } 178 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 92, } } @@ -7053,7 +7044,7 @@ mod __parse__Top { } 180 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 93, } } @@ -7065,170 +7056,170 @@ mod __parse__Top { } 182 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 94, } } 183 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 94, + nonterminal_produced: 95, } } 184 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 1, + nonterminal_produced: 95, } } 185 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 94, + states_to_pop: 1, + nonterminal_produced: 95, } } 186 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 187 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 2, + nonterminal_produced: 95, } } 188 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 189 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 190 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 191 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 94, + states_to_pop: 6, + nonterminal_produced: 95, } } 192 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 193 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 94, + states_to_pop: 7, + nonterminal_produced: 95, } } 194 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 5, + nonterminal_produced: 95, } } 195 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 94, + states_to_pop: 5, + nonterminal_produced: 95, } } 196 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 197 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 94, + states_to_pop: 6, + nonterminal_produced: 95, } } 198 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 199 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 2, + nonterminal_produced: 95, } } 200 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 201 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 202 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 203 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 204 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 94, + states_to_pop: 2, + nonterminal_produced: 95, } } 205 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 94, + nonterminal_produced: 95, } } 206 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 94, + states_to_pop: 3, + nonterminal_produced: 95, } } 207 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 94, + states_to_pop: 4, + nonterminal_produced: 95, } } 208 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 94, + nonterminal_produced: 95, } } 209 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 94, + nonterminal_produced: 95, } } 210 => { @@ -7246,151 +7237,151 @@ mod __parse__Top { 212 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 95, + nonterminal_produced: 96, } } 213 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 95, + states_to_pop: 1, + nonterminal_produced: 96, } } 214 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 95, + states_to_pop: 1, + nonterminal_produced: 96, } } 215 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 95, + states_to_pop: 3, + nonterminal_produced: 96, } } 216 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 95, + states_to_pop: 2, + nonterminal_produced: 96, } } 217 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 95, + nonterminal_produced: 96, } } 218 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 95, + states_to_pop: 6, + nonterminal_produced: 96, } } 219 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 95, + states_to_pop: 4, + nonterminal_produced: 96, } } 220 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 95, + states_to_pop: 7, + nonterminal_produced: 96, } } 221 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 95, + states_to_pop: 5, + nonterminal_produced: 96, } } 222 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 95, + states_to_pop: 5, + nonterminal_produced: 96, } } 223 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 95, + states_to_pop: 3, + nonterminal_produced: 96, } } 224 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 95, + states_to_pop: 6, + nonterminal_produced: 96, } } 225 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 95, + states_to_pop: 4, + nonterminal_produced: 96, } } 226 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 95, + states_to_pop: 2, + nonterminal_produced: 96, } } 227 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 95, + states_to_pop: 3, + nonterminal_produced: 96, } } 228 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 95, + states_to_pop: 4, + nonterminal_produced: 96, } } 229 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 95, + states_to_pop: 4, + nonterminal_produced: 96, } } 230 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 95, + states_to_pop: 3, + nonterminal_produced: 96, } } 231 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 95, + states_to_pop: 2, + nonterminal_produced: 96, } } 232 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 95, + nonterminal_produced: 96, } } 233 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 95, + states_to_pop: 3, + nonterminal_produced: 96, } } 234 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 95, + states_to_pop: 4, + nonterminal_produced: 96, } } 235 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 95, + nonterminal_produced: 96, } } 236 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 95, + nonterminal_produced: 96, } } 237 => { @@ -7401,55 +7392,55 @@ mod __parse__Top { } 238 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 96, } } 239 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 96, + states_to_pop: 1, + nonterminal_produced: 97, } } 240 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 96, + states_to_pop: 2, + nonterminal_produced: 97, } } 241 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 4, nonterminal_produced: 97, } } 242 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 3, nonterminal_produced: 97, } } 243 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 97, + states_to_pop: 1, + nonterminal_produced: 98, } } 244 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 97, + states_to_pop: 2, + nonterminal_produced: 98, } } 245 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 4, nonterminal_produced: 98, } } 246 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 98, } } @@ -7467,7 +7458,7 @@ mod __parse__Top { } 249 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 100, } } @@ -7480,67 +7471,67 @@ mod __parse__Top { 251 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 252 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 253 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 254 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 255 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 256 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 257 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 258 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 259 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 260 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 261 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 100, + nonterminal_produced: 101, } } 262 => { @@ -7551,176 +7542,176 @@ mod __parse__Top { } 263 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 102, + states_to_pop: 1, + nonterminal_produced: 101, } } 264 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 1, nonterminal_produced: 102, } } 265 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 102, + states_to_pop: 6, + nonterminal_produced: 103, } } 266 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 102, + states_to_pop: 5, + nonterminal_produced: 103, } } 267 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 102, + states_to_pop: 7, + nonterminal_produced: 103, } } 268 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 102, + states_to_pop: 6, + nonterminal_produced: 103, } } 269 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 102, + states_to_pop: 5, + nonterminal_produced: 103, } } 270 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 102, + states_to_pop: 4, + nonterminal_produced: 103, } } 271 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 6, nonterminal_produced: 103, } } 272 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, + states_to_pop: 5, nonterminal_produced: 103, } } 273 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 103, + states_to_pop: 7, + nonterminal_produced: 104, } } 274 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 103, + states_to_pop: 6, + nonterminal_produced: 104, } } 275 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 103, + nonterminal_produced: 104, } } 276 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 103, + nonterminal_produced: 104, } } 277 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 103, + states_to_pop: 5, + nonterminal_produced: 104, } } 278 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 103, + states_to_pop: 4, + nonterminal_produced: 104, } } 279 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 103, + states_to_pop: 3, + nonterminal_produced: 104, } } 280 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 103, + states_to_pop: 7, + nonterminal_produced: 104, } } 281 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 103, + states_to_pop: 6, + nonterminal_produced: 104, } } 282 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 103, + nonterminal_produced: 104, } } 283 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 103, + nonterminal_produced: 104, } } 284 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 103, + states_to_pop: 5, + nonterminal_produced: 104, } } 285 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 4, nonterminal_produced: 104, } } 286 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 104, } } 287 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 104, + nonterminal_produced: 105, } } 288 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 104, + nonterminal_produced: 105, } } 289 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 104, + nonterminal_produced: 105, } } 290 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 104, + nonterminal_produced: 105, } } 291 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 104, + nonterminal_produced: 105, } } 292 => { @@ -7731,61 +7722,61 @@ mod __parse__Top { } 293 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 105, } } 294 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 105, + states_to_pop: 1, + nonterminal_produced: 106, } } 295 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 105, + states_to_pop: 0, + nonterminal_produced: 106, } } 296 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 106, } } 297 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 106, } } 298 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 106, + states_to_pop: 1, + nonterminal_produced: 107, } } 299 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 106, + states_to_pop: 0, + nonterminal_produced: 107, } } 300 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 107, } } 301 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 108, + nonterminal_produced: 107, } } 302 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 108, } } @@ -7797,67 +7788,67 @@ mod __parse__Top { } 304 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 109, } } 305 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 306 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 307 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 308 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 309 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 310 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 109, + states_to_pop: 1, + nonterminal_produced: 110, } } 311 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 312 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 109, + nonterminal_produced: 110, } } 313 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 110, } } 314 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 110, } } @@ -7875,7 +7866,7 @@ mod __parse__Top { } 317 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 112, } } @@ -7888,66 +7879,66 @@ mod __parse__Top { 319 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 320 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 321 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 322 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 323 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 324 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 112, + nonterminal_produced: 113, } } 325 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 113, } } 326 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 114, + states_to_pop: 1, + nonterminal_produced: 113, } } 327 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 114, } } 328 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 115, } } 329 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 115, } } @@ -7959,14 +7950,14 @@ mod __parse__Top { } 331 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 116, } } 332 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 116, + nonterminal_produced: 117, } } 333 => { @@ -7978,55 +7969,55 @@ mod __parse__Top { 334 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 118, + nonterminal_produced: 117, } } 335 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 118, } } 336 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 119, } } 337 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 120, + states_to_pop: 2, + nonterminal_produced: 119, } } 338 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 120, } } 339 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 121, } } 340 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 121, } } 341 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 122, } } 342 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 123, + states_to_pop: 2, + nonterminal_produced: 122, } } 343 => { @@ -8037,31 +8028,31 @@ mod __parse__Top { } 344 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 124, } } 345 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 125, + nonterminal_produced: 124, } } 346 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 125, } } 347 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 126, } } 348 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 126, } } @@ -8073,97 +8064,97 @@ mod __parse__Top { } 350 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 0, nonterminal_produced: 127, } } 351 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 128, } } 352 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 128, } } 353 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 129, } } 354 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 129, } } 355 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 130, } } 356 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 0, nonterminal_produced: 130, } } 357 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 130, + states_to_pop: 4, + nonterminal_produced: 131, } } 358 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 131, } } 359 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 6, nonterminal_produced: 131, } } 360 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, + states_to_pop: 1, nonterminal_produced: 132, } } 361 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 2, nonterminal_produced: 132, } } 362 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 5, nonterminal_produced: 133, } } 363 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 7, nonterminal_produced: 133, } } 364 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 134, } } 365 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 134, } } @@ -8181,14 +8172,14 @@ mod __parse__Top { } 368 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 136, } } 369 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 137, + states_to_pop: 1, + nonterminal_produced: 136, } } 370 => { @@ -8199,14 +8190,14 @@ mod __parse__Top { } 371 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 138, } } 372 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 139, + nonterminal_produced: 138, } } 373 => { @@ -8223,37 +8214,37 @@ mod __parse__Top { } 375 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 140, } } 376 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 140, + states_to_pop: 1, + nonterminal_produced: 141, } } 377 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 140, + states_to_pop: 2, + nonterminal_produced: 141, } } 378 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 140, + nonterminal_produced: 141, } } 379 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 4, nonterminal_produced: 141, } } 380 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 141, } } @@ -8271,7 +8262,7 @@ mod __parse__Top { } 383 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 143, } } @@ -8283,50 +8274,50 @@ mod __parse__Top { } 385 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 143, + states_to_pop: 1, + nonterminal_produced: 144, } } 386 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 143, + nonterminal_produced: 144, } } 387 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 143, + states_to_pop: 2, + nonterminal_produced: 144, } } 388 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 143, + nonterminal_produced: 144, } } 389 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, + states_to_pop: 1, nonterminal_produced: 144, } } 390 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 1, nonterminal_produced: 144, } } 391 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 144, + states_to_pop: 10, + nonterminal_produced: 145, } } 392 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 144, + states_to_pop: 7, + nonterminal_produced: 145, } } 393 => { @@ -8337,145 +8328,145 @@ mod __parse__Top { } 394 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, + states_to_pop: 6, nonterminal_produced: 145, } } 395 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 145, + states_to_pop: 9, + nonterminal_produced: 146, } } 396 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 145, + states_to_pop: 8, + nonterminal_produced: 146, } } 397 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 145, + states_to_pop: 10, + nonterminal_produced: 146, } } 398 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 145, + states_to_pop: 9, + nonterminal_produced: 146, } } 399 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 145, + states_to_pop: 7, + nonterminal_produced: 146, } } 400 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 145, + states_to_pop: 6, + nonterminal_produced: 146, } } 401 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 8, - nonterminal_produced: 145, + nonterminal_produced: 146, } } 402 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 145, + nonterminal_produced: 146, } } 403 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 145, + states_to_pop: 8, + nonterminal_produced: 146, } } 404 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 145, + states_to_pop: 7, + nonterminal_produced: 146, } } 405 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 145, + states_to_pop: 9, + nonterminal_produced: 146, } } 406 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 145, + states_to_pop: 8, + nonterminal_produced: 146, } } 407 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 145, + states_to_pop: 6, + nonterminal_produced: 146, } } 408 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 145, + states_to_pop: 5, + nonterminal_produced: 146, } } 409 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 7, nonterminal_produced: 146, } } 410 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 6, nonterminal_produced: 146, } } 411 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 146, + states_to_pop: 2, + nonterminal_produced: 147, } } 412 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 146, + states_to_pop: 1, + nonterminal_produced: 147, } } 413 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 146, + states_to_pop: 3, + nonterminal_produced: 147, } } 414 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 147, } } 415 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 147, } } 416 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 148, } } 417 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 148, } } @@ -8499,49 +8490,49 @@ mod __parse__Top { } 421 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 151, + states_to_pop: 1, + nonterminal_produced: 150, } } 422 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 152, + states_to_pop: 2, + nonterminal_produced: 151, } } 423 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 153, + states_to_pop: 2, + nonterminal_produced: 152, } } 424 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 153, } } 425 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 153, + states_to_pop: 7, + nonterminal_produced: 154, } } 426 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 153, + states_to_pop: 4, + nonterminal_produced: 154, } } 427 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 8, nonterminal_produced: 154, } } 428 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 5, nonterminal_produced: 154, } } @@ -8559,31 +8550,31 @@ mod __parse__Top { } 431 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 156, } } 432 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 156, } } 433 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 156, + states_to_pop: 1, + nonterminal_produced: 157, } } 434 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 156, + states_to_pop: 4, + nonterminal_produced: 157, } } 435 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 157, } } @@ -8595,7 +8586,7 @@ mod __parse__Top { } 437 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 158, } } @@ -8607,13 +8598,13 @@ mod __parse__Top { } 439 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 159, } } 440 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 159, } } @@ -8632,7 +8623,7 @@ mod __parse__Top { 443 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 160, + nonterminal_produced: 161, } } 444 => { @@ -8643,7 +8634,7 @@ mod __parse__Top { } 445 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 161, } } @@ -8655,68 +8646,68 @@ mod __parse__Top { } 447 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 4, nonterminal_produced: 162, } } 448 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 163, } } 449 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 163, + nonterminal_produced: 164, } } 450 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 164, + states_to_pop: 2, + nonterminal_produced: 165, } } 451 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 164, + states_to_pop: 2, + nonterminal_produced: 166, } } 452 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 165, + nonterminal_produced: 166, } } 453 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 166, + states_to_pop: 2, + nonterminal_produced: 167, } } 454 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 167, } } 455 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 167, + states_to_pop: 4, + nonterminal_produced: 168, } } 456 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 168, } } 457 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 168, + states_to_pop: 2, + nonterminal_produced: 169, } } 458 => { @@ -8728,163 +8719,163 @@ mod __parse__Top { 459 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 169, + nonterminal_produced: 170, } } 460 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 169, + states_to_pop: 0, + nonterminal_produced: 170, } } 461 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 169, + nonterminal_produced: 171, } } 462 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 169, + nonterminal_produced: 171, } } 463 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 169, + nonterminal_produced: 171, } } 464 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 171, } } 465 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 171, } } 466 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 171, } } 467 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 172, } } 468 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 172, } } 469 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 172, } } 470 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 170, + nonterminal_produced: 172, } } 471 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 171, + states_to_pop: 1, + nonterminal_produced: 172, } } 472 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 171, + states_to_pop: 1, + nonterminal_produced: 172, } } 473 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 171, + states_to_pop: 1, + nonterminal_produced: 172, } } 474 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 171, + states_to_pop: 2, + nonterminal_produced: 173, } } 475 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 171, + nonterminal_produced: 173, } } 476 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 171, + states_to_pop: 3, + nonterminal_produced: 173, } } 477 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 171, + states_to_pop: 5, + nonterminal_produced: 173, } } 478 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 172, + states_to_pop: 4, + nonterminal_produced: 173, } } 479 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 172, + states_to_pop: 7, + nonterminal_produced: 173, } } 480 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 6, nonterminal_produced: 173, } } 481 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 173, + states_to_pop: 5, + nonterminal_produced: 174, } } 482 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 4, nonterminal_produced: 174, } } 483 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 175, } } 484 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 176, + states_to_pop: 2, + nonterminal_produced: 175, } } 485 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 177, + nonterminal_produced: 176, } } 486 => { @@ -8895,62 +8886,62 @@ mod __parse__Top { } 487 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 1, nonterminal_produced: 178, } } 488 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 178, + states_to_pop: 3, + nonterminal_produced: 179, } } 489 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 178, + states_to_pop: 3, + nonterminal_produced: 179, } } 490 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 178, + nonterminal_produced: 180, } } 491 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 179, + states_to_pop: 8, + nonterminal_produced: 180, } } 492 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 179, + states_to_pop: 8, + nonterminal_produced: 180, } } 493 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 179, + states_to_pop: 7, + nonterminal_produced: 180, } } 494 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 179, + nonterminal_produced: 181, } } 495 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 179, + nonterminal_produced: 181, } } 496 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 180, + states_to_pop: 1, + nonterminal_produced: 181, } } 497 => { @@ -8967,1765 +8958,1765 @@ mod __parse__Top { } 499 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 182, } } 500 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 182, + nonterminal_produced: 183, } } 501 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 183, + states_to_pop: 1, + nonterminal_produced: 184, } } 502 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 184, } } 503 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 184, + nonterminal_produced: 185, } } 504 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 185, } } 505 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 185, + states_to_pop: 2, + nonterminal_produced: 186, } } 506 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 186, + states_to_pop: 2, + nonterminal_produced: 187, } } 507 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 186, + states_to_pop: 1, + nonterminal_produced: 187, } } 508 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 187, + states_to_pop: 2, + nonterminal_produced: 188, } } 509 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 187, + states_to_pop: 1, + nonterminal_produced: 188, } } 510 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 188, + nonterminal_produced: 189, } } 511 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 188, + nonterminal_produced: 189, } } 512 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 189, + states_to_pop: 1, + nonterminal_produced: 190, } } 513 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 189, + states_to_pop: 3, + nonterminal_produced: 190, } } 514 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 189, + states_to_pop: 1, + nonterminal_produced: 191, } } 515 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 189, + nonterminal_produced: 191, } } 516 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 190, + nonterminal_produced: 192, } } 517 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 190, + nonterminal_produced: 192, } } 518 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 190, + nonterminal_produced: 192, } } 519 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 190, + nonterminal_produced: 192, } } 520 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 191, + states_to_pop: 3, + nonterminal_produced: 193, } } 521 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 191, + states_to_pop: 1, + nonterminal_produced: 193, } } 522 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 192, + states_to_pop: 5, + nonterminal_produced: 193, } } 523 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 192, + nonterminal_produced: 193, } } 524 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 193, + nonterminal_produced: 194, } } 525 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 193, + nonterminal_produced: 194, } } 526 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 194, + nonterminal_produced: 195, } } 527 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 194, + nonterminal_produced: 195, } } 528 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 195, + nonterminal_produced: 196, } } 529 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 195, + nonterminal_produced: 196, } } 530 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 196, + nonterminal_produced: 197, } } 531 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 196, + nonterminal_produced: 197, } } 532 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 197, + nonterminal_produced: 198, } } 533 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 197, + nonterminal_produced: 198, } } 534 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 198, + nonterminal_produced: 199, } } 535 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 198, + nonterminal_produced: 199, } } 536 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 199, + nonterminal_produced: 200, } } 537 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 199, + nonterminal_produced: 200, } } 538 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 200, + nonterminal_produced: 201, } } 539 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 200, + states_to_pop: 3, + nonterminal_produced: 201, } } 540 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 201, + states_to_pop: 1, + nonterminal_produced: 202, } } 541 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 201, + states_to_pop: 3, + nonterminal_produced: 202, } } 542 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 202, + states_to_pop: 1, + nonterminal_produced: 203, } } 543 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 202, + nonterminal_produced: 203, } } 544 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 203, + states_to_pop: 2, + nonterminal_produced: 204, } } 545 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 203, + states_to_pop: 1, + nonterminal_produced: 204, } } 546 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 204, + states_to_pop: 2, + nonterminal_produced: 205, } } 547 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 204, + states_to_pop: 1, + nonterminal_produced: 205, } } 548 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 205, + nonterminal_produced: 206, } } 549 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 205, + nonterminal_produced: 206, } } 550 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 205, + states_to_pop: 1, + nonterminal_produced: 207, } } 551 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 206, + states_to_pop: 3, + nonterminal_produced: 207, } } 552 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 206, + states_to_pop: 1, + nonterminal_produced: 208, } } 553 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 206, + states_to_pop: 3, + nonterminal_produced: 208, } } 554 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 208, } } 555 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 207, + states_to_pop: 1, + nonterminal_produced: 209, } } 556 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 209, } } 557 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 209, } } 558 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 559 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 9, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 560 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 10, + nonterminal_produced: 210, } } 561 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 562 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 11, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 563 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 9, + nonterminal_produced: 210, } } 564 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 565 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 10, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 566 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 11, + nonterminal_produced: 210, } } 567 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 568 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 9, + nonterminal_produced: 210, } } 569 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 10, + nonterminal_produced: 210, } } 570 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 571 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 572 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 573 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 574 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 575 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 576 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 577 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 8, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 578 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 207, + states_to_pop: 9, + nonterminal_produced: 210, } } 579 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 580 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 581 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 582 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 2, + nonterminal_produced: 210, } } 583 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 584 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 585 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 586 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 8, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 587 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 9, + nonterminal_produced: 210, } } 588 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 589 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 590 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 591 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 592 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 9, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 593 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 10, + nonterminal_produced: 210, } } 594 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 595 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 596 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 9, + nonterminal_produced: 210, } } 597 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 598 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 599 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 600 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 601 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 602 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 603 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 604 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 605 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 207, + states_to_pop: 8, + nonterminal_produced: 210, } } 606 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 607 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 608 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 609 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 1, + nonterminal_produced: 210, } } 610 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 611 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 612 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 613 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 614 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 7, + nonterminal_produced: 210, } } 615 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 616 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 617 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 618 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 619 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 620 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 6, + nonterminal_produced: 210, } } 621 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 622 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 623 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 2, + nonterminal_produced: 210, } } 624 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 625 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 626 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 627 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 207, + states_to_pop: 3, + nonterminal_produced: 210, } } 628 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 207, + states_to_pop: 5, + nonterminal_produced: 210, } } 629 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 207, + states_to_pop: 4, + nonterminal_produced: 210, } } 630 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 631 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 207, + nonterminal_produced: 210, } } 632 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 210, } } 633 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 208, + states_to_pop: 2, + nonterminal_produced: 210, } } 634 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 208, + states_to_pop: 2, + nonterminal_produced: 210, } } 635 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 1, + nonterminal_produced: 210, } } 636 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 637 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 9, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 638 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 10, + nonterminal_produced: 211, } } 639 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 640 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 11, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 641 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 9, + nonterminal_produced: 211, } } 642 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 643 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 10, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 644 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 11, + nonterminal_produced: 211, } } 645 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 646 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 9, + nonterminal_produced: 211, } } 647 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 10, + nonterminal_produced: 211, } } 648 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 649 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 650 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 651 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 652 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 653 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 654 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 655 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 8, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 656 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 208, + states_to_pop: 9, + nonterminal_produced: 211, } } 657 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 658 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 659 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 660 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 2, + nonterminal_produced: 211, } } 661 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 662 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 663 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 664 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 8, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 665 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 9, + nonterminal_produced: 211, } } 666 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 9, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 667 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 668 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 669 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 670 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 9, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 671 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 10, + nonterminal_produced: 211, } } 672 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 673 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 674 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 9, + nonterminal_produced: 211, } } 675 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 676 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 677 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 678 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 679 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 8, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 680 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 681 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 682 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 683 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 208, + states_to_pop: 8, + nonterminal_produced: 211, } } 684 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 685 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 686 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 687 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 1, + nonterminal_produced: 211, } } 688 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 689 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 690 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 691 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 6, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 692 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 7, + nonterminal_produced: 211, } } 693 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 694 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 695 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 696 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 697 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 698 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 6, + nonterminal_produced: 211, } } 699 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 700 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 701 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 2, + nonterminal_produced: 211, } } 702 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 703 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 704 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 705 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 208, + states_to_pop: 3, + nonterminal_produced: 211, } } 706 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 208, + states_to_pop: 5, + nonterminal_produced: 211, } } 707 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 208, + states_to_pop: 4, + nonterminal_produced: 211, } } 708 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 709 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 208, + nonterminal_produced: 211, } } 710 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 209, + states_to_pop: 3, + nonterminal_produced: 211, } } 711 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 209, + states_to_pop: 2, + nonterminal_produced: 211, } } 712 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 210, + states_to_pop: 2, + nonterminal_produced: 211, } } 713 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 210, + states_to_pop: 1, + nonterminal_produced: 211, } } 714 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 210, + states_to_pop: 1, + nonterminal_produced: 212, } } 715 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 210, + states_to_pop: 0, + nonterminal_produced: 212, } } 716 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 210, + states_to_pop: 4, + nonterminal_produced: 213, } } 717 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 210, + states_to_pop: 3, + nonterminal_produced: 213, } } 718 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 210, + states_to_pop: 5, + nonterminal_produced: 213, } } 719 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 210, + states_to_pop: 4, + nonterminal_produced: 213, } } 720 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 211, + states_to_pop: 2, + nonterminal_produced: 213, } } 721 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 211, + states_to_pop: 1, + nonterminal_produced: 213, } } 722 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 211, + states_to_pop: 3, + nonterminal_produced: 213, } } 723 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 211, + states_to_pop: 2, + nonterminal_produced: 213, } } 724 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 211, + states_to_pop: 4, + nonterminal_produced: 214, } } 725 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 211, + states_to_pop: 3, + nonterminal_produced: 214, } } 726 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 211, + states_to_pop: 5, + nonterminal_produced: 214, } } 727 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 211, + states_to_pop: 4, + nonterminal_produced: 214, } } 728 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 212, + states_to_pop: 2, + nonterminal_produced: 214, } } 729 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 212, + states_to_pop: 1, + nonterminal_produced: 214, } } 730 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 213, + states_to_pop: 3, + nonterminal_produced: 214, } } 731 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 214, } } 732 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 214, + states_to_pop: 3, + nonterminal_produced: 215, } } 733 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 215, } } 734 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 215, + states_to_pop: 1, + nonterminal_produced: 216, } } 735 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 216, + states_to_pop: 1, + nonterminal_produced: 217, } } 736 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 216, + states_to_pop: 1, + nonterminal_produced: 217, } } 737 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 216, + nonterminal_produced: 218, } } 738 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 216, + states_to_pop: 0, + nonterminal_produced: 218, } } 739 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 217, + states_to_pop: 2, + nonterminal_produced: 219, } } 740 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 217, + states_to_pop: 2, + nonterminal_produced: 219, } } 741 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 218, + states_to_pop: 1, + nonterminal_produced: 219, } } 742 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 218, + nonterminal_produced: 219, } } 743 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 219, + states_to_pop: 3, + nonterminal_produced: 220, } } 744 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 219, + states_to_pop: 1, + nonterminal_produced: 220, } } 745 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 219, + states_to_pop: 3, + nonterminal_produced: 221, } } 746 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 219, + states_to_pop: 1, + nonterminal_produced: 221, } } 747 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 219, + states_to_pop: 0, + nonterminal_produced: 222, } } 748 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 219, + states_to_pop: 2, + nonterminal_produced: 222, } } 749 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 219, + states_to_pop: 4, + nonterminal_produced: 222, } } 750 => { - __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 220, + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 5, + nonterminal_produced: 222, } } 751 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 220, + states_to_pop: 3, + nonterminal_produced: 222, } } 752 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 220, + states_to_pop: 4, + nonterminal_produced: 222, } } 753 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 221, + states_to_pop: 2, + nonterminal_produced: 222, } } 754 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 221, + states_to_pop: 1, + nonterminal_produced: 223, } } 755 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 221, + nonterminal_produced: 223, } } 756 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 221, + states_to_pop: 2, + nonterminal_produced: 223, } } 757 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 221, + states_to_pop: 3, + nonterminal_produced: 224, } } 758 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 221, + states_to_pop: 2, + nonterminal_produced: 224, } } 759 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 221, + states_to_pop: 4, + nonterminal_produced: 224, } } 760 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 221, + states_to_pop: 5, + nonterminal_produced: 224, } } 761 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 221, + states_to_pop: 4, + nonterminal_produced: 224, } } 762 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 222, + states_to_pop: 3, + nonterminal_produced: 224, } } 763 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 222, + states_to_pop: 2, + nonterminal_produced: 224, } } 764 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 223, + states_to_pop: 4, + nonterminal_produced: 224, } } 765 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 223, + states_to_pop: 3, + nonterminal_produced: 224, } } 766 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 224, + states_to_pop: 2, + nonterminal_produced: 225, } } 767 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 224, + nonterminal_produced: 225, } } 768 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 225, + states_to_pop: 3, + nonterminal_produced: 226, } } 769 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 225, + nonterminal_produced: 226, } } 770 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 226, + states_to_pop: 3, + nonterminal_produced: 227, } } 771 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 226, + states_to_pop: 1, + nonterminal_produced: 227, } } 772 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 226, + states_to_pop: 1, + nonterminal_produced: 228, } } 773 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 226, + states_to_pop: 1, + nonterminal_produced: 228, } } 774 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 227, + states_to_pop: 5, + nonterminal_produced: 229, } } 775 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 227, + states_to_pop: 6, + nonterminal_produced: 229, } } 776 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 228, + states_to_pop: 4, + nonterminal_produced: 229, } } 777 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 228, + states_to_pop: 5, + nonterminal_produced: 229, } } 778 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 229, + nonterminal_produced: 230, } } 779 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 229, + states_to_pop: 2, + nonterminal_produced: 230, } } 780 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 230, + states_to_pop: 2, + nonterminal_produced: 231, } } 781 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 231, } } 782 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 232, } } 783 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 230, + states_to_pop: 0, + nonterminal_produced: 232, } } 784 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 785 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 786 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 787 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 788 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 789 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 230, + nonterminal_produced: 233, } } 790 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 231, + states_to_pop: 1, + nonterminal_produced: 233, } } 791 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 232, + states_to_pop: 1, + nonterminal_produced: 233, } } 792 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 233, } } @@ -10738,289 +10729,289 @@ mod __parse__Top { 794 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 234, + nonterminal_produced: 233, } } 795 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 234, } } 796 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 235, } } 797 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 236, } } 798 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 1, nonterminal_produced: 236, } } 799 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 237, } } 800 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 0, nonterminal_produced: 237, } } 801 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 237, + states_to_pop: 1, + nonterminal_produced: 238, } } 802 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 237, + states_to_pop: 1, + nonterminal_produced: 239, } } 803 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 237, + states_to_pop: 0, + nonterminal_produced: 239, } } 804 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 237, + states_to_pop: 3, + nonterminal_produced: 240, } } 805 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 237, + nonterminal_produced: 240, } } 806 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 237, + states_to_pop: 2, + nonterminal_produced: 240, } } 807 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 237, + nonterminal_produced: 240, } } 808 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 237, + states_to_pop: 1, + nonterminal_produced: 240, } } 809 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 238, + states_to_pop: 2, + nonterminal_produced: 240, } } 810 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 238, + nonterminal_produced: 240, } } 811 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 238, + states_to_pop: 5, + nonterminal_produced: 240, } } 812 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 238, + nonterminal_produced: 240, } } 813 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 238, + states_to_pop: 4, + nonterminal_produced: 240, } } 814 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 238, + states_to_pop: 1, + nonterminal_produced: 241, } } 815 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 238, + states_to_pop: 4, + nonterminal_produced: 241, } } 816 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 238, + states_to_pop: 3, + nonterminal_produced: 241, } } 817 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 238, + states_to_pop: 3, + nonterminal_produced: 241, } } 818 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 239, + states_to_pop: 2, + nonterminal_produced: 241, } } 819 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 239, + states_to_pop: 3, + nonterminal_produced: 241, } } 820 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 239, + nonterminal_produced: 241, } } 821 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 239, + states_to_pop: 2, + nonterminal_produced: 241, } } 822 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 240, + states_to_pop: 1, + nonterminal_produced: 241, } } 823 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 240, + states_to_pop: 1, + nonterminal_produced: 242, } } 824 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 2, - nonterminal_produced: 240, + nonterminal_produced: 242, } } 825 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 240, + states_to_pop: 2, + nonterminal_produced: 242, } } 826 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 240, + states_to_pop: 1, + nonterminal_produced: 242, } } 827 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 241, + nonterminal_produced: 243, } } 828 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 241, + states_to_pop: 4, + nonterminal_produced: 243, } } 829 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 242, + states_to_pop: 2, + nonterminal_produced: 243, } } 830 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 242, + states_to_pop: 3, + nonterminal_produced: 243, } } 831 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, + states_to_pop: 4, nonterminal_produced: 243, } } 832 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 243, + states_to_pop: 3, + nonterminal_produced: 244, } } 833 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 243, + nonterminal_produced: 244, } } 834 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 244, + states_to_pop: 3, + nonterminal_produced: 245, } } 835 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 244, + states_to_pop: 1, + nonterminal_produced: 245, } } 836 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 5, - nonterminal_produced: 245, + nonterminal_produced: 246, } } 837 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 245, + nonterminal_produced: 246, } } 838 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 245, + nonterminal_produced: 246, } } 839 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 246, + nonterminal_produced: 247, } } 840 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 247, } } 841 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 247, + states_to_pop: 5, + nonterminal_produced: 248, } } 842 => { @@ -11044,12 +11035,12 @@ mod __parse__Top { 845 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 249, + nonterminal_produced: 250, } } 846 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 0, nonterminal_produced: 250, } } @@ -11067,110 +11058,110 @@ mod __parse__Top { } 849 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 252, } } 850 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 1, nonterminal_produced: 252, } } 851 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 252, + states_to_pop: 1, + nonterminal_produced: 253, } } 852 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 253, + states_to_pop: 1, + nonterminal_produced: 254, } } 853 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 253, + states_to_pop: 1, + nonterminal_produced: 254, } } 854 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 253, + states_to_pop: 2, + nonterminal_produced: 255, } } 855 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 253, + states_to_pop: 2, + nonterminal_produced: 255, } } 856 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 10, - nonterminal_produced: 253, + states_to_pop: 3, + nonterminal_produced: 255, } } 857 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 253, + states_to_pop: 10, + nonterminal_produced: 256, } } 858 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 7, - nonterminal_produced: 253, + nonterminal_produced: 256, } } 859 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 253, + states_to_pop: 7, + nonterminal_produced: 256, } } 860 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 253, + states_to_pop: 4, + nonterminal_produced: 256, } } 861 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 254, + states_to_pop: 10, + nonterminal_produced: 256, } } 862 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 254, + states_to_pop: 7, + nonterminal_produced: 256, } } 863 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 255, + states_to_pop: 7, + nonterminal_produced: 256, } } 864 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 255, + states_to_pop: 4, + nonterminal_produced: 256, } } 865 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 6, nonterminal_produced: 256, } } 866 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 256, + nonterminal_produced: 257, } } 867 => { @@ -11182,24 +11173,24 @@ mod __parse__Top { 868 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 257, + nonterminal_produced: 258, } } 869 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 258, } } 870 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, + states_to_pop: 3, nonterminal_produced: 259, } } 871 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 3, nonterminal_produced: 259, } } @@ -11211,80 +11202,80 @@ mod __parse__Top { } 873 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 260, } } 874 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 260, + states_to_pop: 1, + nonterminal_produced: 261, } } 875 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 260, + states_to_pop: 5, + nonterminal_produced: 262, } } 876 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 261, + nonterminal_produced: 262, } } 877 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 261, + nonterminal_produced: 263, } } 878 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 262, + nonterminal_produced: 263, } } 879 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, - nonterminal_produced: 262, + states_to_pop: 2, + nonterminal_produced: 263, } } 880 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 2, nonterminal_produced: 263, } } 881 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 263, + states_to_pop: 4, + nonterminal_produced: 264, } } 882 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 264, } } 883 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 264, + nonterminal_produced: 265, } } 884 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 264, + states_to_pop: 0, + nonterminal_produced: 265, } } 885 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 265, + states_to_pop: 3, + nonterminal_produced: 266, } } 886 => { @@ -11295,179 +11286,209 @@ mod __parse__Top { } 887 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, + states_to_pop: 1, nonterminal_produced: 267, } } 888 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 267, } } 889 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 1, - nonterminal_produced: 268, + nonterminal_produced: 267, } } 890 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 268, } } 891 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 269, } } 892 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 7, nonterminal_produced: 270, } } 893 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 4, nonterminal_produced: 270, } } 894 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, + states_to_pop: 1, nonterminal_produced: 271, } } 895 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 271, } } 896 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 271, + states_to_pop: 1, + nonterminal_produced: 272, } } 897 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 271, + states_to_pop: 1, + nonterminal_produced: 272, } } 898 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 7, - nonterminal_produced: 271, + states_to_pop: 3, + nonterminal_produced: 273, } } 899 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 271, + states_to_pop: 4, + nonterminal_produced: 274, } } 900 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 271, + states_to_pop: 3, + nonterminal_produced: 274, } } 901 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, - nonterminal_produced: 271, + states_to_pop: 6, + nonterminal_produced: 274, } } 902 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 6, - nonterminal_produced: 271, + states_to_pop: 4, + nonterminal_produced: 274, } } 903 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 4, - nonterminal_produced: 271, + states_to_pop: 7, + nonterminal_produced: 274, } } 904 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 271, + states_to_pop: 5, + nonterminal_produced: 274, } } 905 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, - nonterminal_produced: 271, + states_to_pop: 5, + nonterminal_produced: 274, } } 906 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 272, + states_to_pop: 3, + nonterminal_produced: 274, } } 907 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 5, - nonterminal_produced: 273, + states_to_pop: 6, + nonterminal_produced: 274, } } 908 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 4, - nonterminal_produced: 273, + nonterminal_produced: 274, } } 909 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 274, } } 910 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 2, nonterminal_produced: 274, } } 911 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 3, + states_to_pop: 1, nonterminal_produced: 275, } } 912 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 275, + states_to_pop: 5, + nonterminal_produced: 276, } } 913 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 4, nonterminal_produced: 276, } } 914 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 276, + states_to_pop: 3, + nonterminal_produced: 277, } } 915 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 277, + } + } + 916 => { __state_machine::SimulatedReduce::Reduce { states_to_pop: 3, - nonterminal_produced: 276, + nonterminal_produced: 278, + } + } + 917 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 278, + } + } + 918 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 279, + } + } + 919 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 279, + } + } + 920 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 279, } } - 916 => __state_machine::SimulatedReduce::Accept, + 921 => __state_machine::SimulatedReduce::Accept, _ => panic!("invalid reduction index {}", __reduce_index) } } @@ -11613,528 +11634,528 @@ mod __parse__Top { __reduce21(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 22 => { - __reduce22(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 23 => { - __reduce23(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 24 => { - __reduce24(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 25 => { - // ("," >) = ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(947); + // ("," >) = ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(949); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action947::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action949::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 13) } - 26 => { - // ("," >) = ",", "*", ",", KwargParameter => ActionFn(948); + 23 => { + // ("," >) = ",", "*", ",", KwargParameter => ActionFn(950); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action948::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action950::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 13) } - 27 => { - // ("," >) = ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(949); + 24 => { + // ("," >) = ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(951); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action949::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action951::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (6, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (6, 13) } - 28 => { - // ("," >) = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(950); + 25 => { + // ("," >) = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(952); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action950::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action952::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 13) } - 29 => { - // ("," >) = ",", "*", StarTypedParameter => ActionFn(951); + 26 => { + // ("," >) = ",", "*", StarTypedParameter => ActionFn(953); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action951::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action953::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 13) } - 30 => { - // ("," >) = ",", "*" => ActionFn(952); + 27 => { + // ("," >) = ",", "*" => ActionFn(954); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action952::<>(mode, __sym0, __sym1) { + let __nt = match super::__action954::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 13) } - 31 => { - // ("," >) = ",", "*", StarTypedParameter, ("," >)+ => ActionFn(953); + 28 => { + // ("," >) = ",", "*", StarTypedParameter, ("," >)+ => ActionFn(955); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action953::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action955::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 13) } - 32 => { - // ("," >) = ",", "*", ("," >)+ => ActionFn(954); + 29 => { + // ("," >) = ",", "*", ("," >)+ => ActionFn(956); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action954::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action956::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 15) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 13) } - 33 => { - // ("," >)? = ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(971); + 30 => { + // ("," >)? = ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(973); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action971::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action973::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (5, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (5, 14) } - 34 => { - // ("," >)? = ",", "*", ",", KwargParameter => ActionFn(972); + 31 => { + // ("," >)? = ",", "*", ",", KwargParameter => ActionFn(974); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action972::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action974::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (4, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (4, 14) } - 35 => { - // ("," >)? = ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(973); + 32 => { + // ("," >)? = ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(975); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action973::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action975::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (6, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (6, 14) } - 36 => { - // ("," >)? = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(974); + 33 => { + // ("," >)? = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(976); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action974::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action976::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (5, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (5, 14) } - 37 => { - // ("," >)? = ",", "*", StarTypedParameter => ActionFn(975); + 34 => { + // ("," >)? = ",", "*", StarTypedParameter => ActionFn(977); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action975::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action977::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (3, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (3, 14) } - 38 => { - // ("," >)? = ",", "*" => ActionFn(976); + 35 => { + // ("," >)? = ",", "*" => ActionFn(978); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action976::<>(mode, __sym0, __sym1) { + let __nt = match super::__action978::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (2, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (2, 14) } - 39 => { - // ("," >)? = ",", "*", StarTypedParameter, ("," >)+ => ActionFn(977); + 36 => { + // ("," >)? = ",", "*", StarTypedParameter, ("," >)+ => ActionFn(979); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action977::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action979::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (4, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (4, 14) } - 40 => { - // ("," >)? = ",", "*", ("," >)+ => ActionFn(978); + 37 => { + // ("," >)? = ",", "*", ("," >)+ => ActionFn(980); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action978::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action980::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (3, 16) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (3, 14) } - 41 => { - __reduce41(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 38 => { + __reduce38(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 42 => { - // ("," >) = ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1007); + 39 => { + // ("," >) = ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1009); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1007::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1009::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 15) } - 43 => { - // ("," >) = ",", "*", ",", KwargParameter => ActionFn(1008); + 40 => { + // ("," >) = ",", "*", ",", KwargParameter => ActionFn(1010); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1008::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1010::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 15) } - 44 => { - // ("," >) = ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1009); + 41 => { + // ("," >) = ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1011); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1009::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1011::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (6, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (6, 15) } - 45 => { - // ("," >) = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1010); + 42 => { + // ("," >) = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1012); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1010::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1012::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 15) } - 46 => { - // ("," >) = ",", "*", StarUntypedParameter => ActionFn(1011); + 43 => { + // ("," >) = ",", "*", StarUntypedParameter => ActionFn(1013); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1011::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1013::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 15) } - 47 => { - // ("," >) = ",", "*" => ActionFn(1012); + 44 => { + // ("," >) = ",", "*" => ActionFn(1014); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1012::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1014::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 15) } - 48 => { - // ("," >) = ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1013); + 45 => { + // ("," >) = ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1015); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1013::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1015::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 15) } - 49 => { - // ("," >) = ",", "*", ("," >)+ => ActionFn(1014); + 46 => { + // ("," >) = ",", "*", ("," >)+ => ActionFn(1016); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1014::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1016::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 17) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 15) } - 50 => { - // ("," >)? = ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1031); + 47 => { + // ("," >)? = ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1033); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1031::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1033::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (5, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (5, 16) } - 51 => { - // ("," >)? = ",", "*", ",", KwargParameter => ActionFn(1032); + 48 => { + // ("," >)? = ",", "*", ",", KwargParameter => ActionFn(1034); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1032::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1034::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (4, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (4, 16) } - 52 => { - // ("," >)? = ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1033); + 49 => { + // ("," >)? = ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1035); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1033::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1035::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (6, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (6, 16) } - 53 => { - // ("," >)? = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1034); + 50 => { + // ("," >)? = ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1036); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1034::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1036::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (5, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (5, 16) } - 54 => { - // ("," >)? = ",", "*", StarUntypedParameter => ActionFn(1035); + 51 => { + // ("," >)? = ",", "*", StarUntypedParameter => ActionFn(1037); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1035::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1037::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (3, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (3, 16) } - 55 => { - // ("," >)? = ",", "*" => ActionFn(1036); + 52 => { + // ("," >)? = ",", "*" => ActionFn(1038); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1036::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1038::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (2, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (2, 16) } - 56 => { - // ("," >)? = ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1037); + 53 => { + // ("," >)? = ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1039); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); - let __sym2 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant11(__symbols); + let __sym2 = __pop_Variant63(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1037::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1039::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (4, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (4, 16) } - 57 => { - // ("," >)? = ",", "*", ("," >)+ => ActionFn(1038); + 54 => { + // ("," >)? = ",", "*", ("," >)+ => ActionFn(1040); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); + let __sym2 = __pop_Variant11(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1038::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1040::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (3, 18) + __symbols.push((__start, __Symbol::Variant13(__nt), __end)); + (3, 16) + } + 55 => { + __reduce55(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 56 => { + __reduce56(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 57 => { + __reduce57(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 58 => { __reduce58(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12449,53 +12470,64 @@ mod __parse__Top { __reduce161(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 162 => { - // ArgumentList = FunctionArgument => ActionFn(1511); - let __sym0 = __pop_Variant32(__symbols); + // Arguments = "(", FunctionArgument, ")" => ActionFn(1518); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant30(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action1511::<>(mode, __sym0) { + let __end = __sym2.2; + let __nt = match super::__action1518::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant51(__nt), __end)); - (1, 85) + __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + (3, 85) } 163 => { - // ArgumentList = => ActionFn(1512); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = match super::__action1512::<>(mode, &__start, &__end) { + // Arguments = "(", ")" => ActionFn(1519); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0; + let __end = __sym1.2; + let __nt = match super::__action1519::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant51(__nt), __end)); - (0, 85) + __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + (2, 85) } 164 => { - // ArgumentList = ( ",")+, FunctionArgument => ActionFn(1513); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant32(__symbols); - let __sym0 = __pop_Variant33(__symbols); + // Arguments = "(", ( ",")+, FunctionArgument, ")" => ActionFn(1520); + assert!(__symbols.len() >= 4); + let __sym3 = __pop_Variant0(__symbols); + let __sym2 = __pop_Variant30(__symbols); + let __sym1 = __pop_Variant31(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = match super::__action1513::<>(mode, __sym0, __sym1) { + let __end = __sym3.2; + let __nt = match super::__action1520::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant51(__nt), __end)); - (2, 85) + __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + (4, 85) } 165 => { - // ArgumentList = ( ",")+ => ActionFn(1514); - let __sym0 = __pop_Variant33(__symbols); + // Arguments = "(", ( ",")+, ")" => ActionFn(1521); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant31(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action1514::<>(mode, __sym0) { + let __end = __sym2.2; + let __nt = match super::__action1521::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant51(__nt), __end)); - (1, 85) + __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + (3, 85) } 166 => { __reduce166(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12510,25 +12542,25 @@ mod __parse__Top { __reduce169(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 170 => { - // AsPattern = OrPattern, "as", Identifier => ActionFn(1192); + __reduce170(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 171 => { + __reduce171(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 172 => { + // AsPattern = OrPattern, "as", Identifier => ActionFn(1197); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1192::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1197::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 88) - } - 171 => { - __reduce171(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 172 => { - __reduce172(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 89) } 173 => { __reduce173(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12555,22 +12587,22 @@ mod __parse__Top { __reduce180(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 181 => { - // Atom<"all"> = (@L string @R)+ => ActionFn(713); - let __sym0 = __pop_Variant44(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action713::<>(mode, __sym0) { - Ok(v) => v, - Err(e) => return Some(Err(e)), - }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + __reduce181(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 182 => { __reduce182(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 183 => { - __reduce183(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // Atom<"all"> = (@L string @R)+ => ActionFn(716); + let __sym0 = __pop_Variant42(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = match super::__action716::<>(mode, __sym0) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } 184 => { __reduce184(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12588,171 +12620,171 @@ mod __parse__Top { __reduce188(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 189 => { - // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ",", ")" => ActionFn(1201); + __reduce189(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 190 => { + __reduce190(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 191 => { + // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ",", ")" => ActionFn(1206); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1201::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1206::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (6, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (6, 95) } - 190 => { - // Atom<"all"> = "(", NamedOrStarExpr, ",", ")" => ActionFn(1202); + 192 => { + // Atom<"all"> = "(", NamedOrStarExpr, ",", ")" => ActionFn(1207); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1202::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1207::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - 191 => { - // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1203); + 193 => { + // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1208); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant18(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1203::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1208::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (7, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (7, 95) } - 192 => { - // Atom<"all"> = "(", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1204); + 194 => { + // Atom<"all"> = "(", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1209); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant18(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1204::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1209::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 95) } - 193 => { - // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ")" => ActionFn(1205); + 195 => { + // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ")" => ActionFn(1210); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1205::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1210::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 95) } - 194 => { - // Atom<"all"> = "(", NamedOrStarExpr, ")" => ActionFn(1206); + 196 => { + // Atom<"all"> = "(", NamedOrStarExpr, ")" => ActionFn(1211); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1206::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1211::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - 195 => { - // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ")" => ActionFn(1207); + 197 => { + // Atom<"all"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ")" => ActionFn(1212); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant18(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1207::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1212::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (6, 94) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (6, 95) } - 196 => { - // Atom<"all"> = "(", NamedOrStarExpr, ("," )+, ")" => ActionFn(1208); + 198 => { + // Atom<"all"> = "(", NamedOrStarExpr, ("," )+, ")" => ActionFn(1213); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant18(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1208::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1213::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) - } - 197 => { - __reduce197(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 198 => { - __reduce198(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } 199 => { __reduce199(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 200 => { - // Atom<"all"> = "(", "**", Expression<"all">, ")" => ActionFn(1211); + __reduce200(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 201 => { + __reduce201(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 202 => { + // Atom<"all"> = "(", "**", Expression<"all">, ")" => ActionFn(1216); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1211::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1216::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) - } - 201 => { - __reduce201(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 202 => { - __reduce202(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } 203 => { __reduce203(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12776,22 +12808,22 @@ mod __parse__Top { __reduce209(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 210 => { - // Atom<"no-withitems"> = (@L string @R)+ => ActionFn(733); - let __sym0 = __pop_Variant44(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action733::<>(mode, __sym0) { - Ok(v) => v, - Err(e) => return Some(Err(e)), - }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + __reduce210(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 211 => { __reduce211(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 212 => { - __reduce212(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // Atom<"no-withitems"> = (@L string @R)+ => ActionFn(736); + let __sym0 = __pop_Variant42(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = match super::__action736::<>(mode, __sym0) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } 213 => { __reduce213(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -12803,171 +12835,171 @@ mod __parse__Top { __reduce215(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 216 => { - // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ",", ")" => ActionFn(1224); + __reduce216(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 217 => { + __reduce217(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 218 => { + // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ",", ")" => ActionFn(1229); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1224::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1229::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (6, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (6, 96) } - 217 => { - // Atom<"no-withitems"> = "(", NamedOrStarExpr, ",", ")" => ActionFn(1225); + 219 => { + // Atom<"no-withitems"> = "(", NamedOrStarExpr, ",", ")" => ActionFn(1230); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1225::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1230::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } - 218 => { - // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1226); + 220 => { + // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1231); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant18(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1226::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1231::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (7, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (7, 96) } - 219 => { - // Atom<"no-withitems"> = "(", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1227); + 221 => { + // Atom<"no-withitems"> = "(", NamedOrStarExpr, ("," )+, ",", ")" => ActionFn(1232); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant18(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1227::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1232::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 96) } - 220 => { - // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ")" => ActionFn(1228); + 222 => { + // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ")" => ActionFn(1233); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1228::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1233::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 96) } - 221 => { - // Atom<"no-withitems"> = "(", NamedOrStarExpr, ")" => ActionFn(1229); + 223 => { + // Atom<"no-withitems"> = "(", NamedOrStarExpr, ")" => ActionFn(1234); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1229::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1234::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 96) } - 222 => { - // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ")" => ActionFn(1230); + 224 => { + // Atom<"no-withitems"> = "(", OneOrMore>, ",", NamedOrStarExpr, ("," )+, ")" => ActionFn(1235); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant18(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1230::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1235::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (6, 95) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (6, 96) } - 223 => { - // Atom<"no-withitems"> = "(", NamedOrStarExpr, ("," )+, ")" => ActionFn(1231); + 225 => { + // Atom<"no-withitems"> = "(", NamedOrStarExpr, ("," )+, ")" => ActionFn(1236); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant18(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1231::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1236::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) - } - 224 => { - __reduce224(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 225 => { - __reduce225(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } 226 => { __reduce226(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 227 => { - // Atom<"no-withitems"> = "(", "**", Expression<"all">, ")" => ActionFn(1234); + __reduce227(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 228 => { + __reduce228(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 229 => { + // Atom<"no-withitems"> = "(", "**", Expression<"all">, ")" => ActionFn(1239); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1234::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1239::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) - } - 228 => { - __reduce228(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 229 => { - __reduce229(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } 230 => { __reduce230(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -13624,74 +13656,85 @@ mod __parse__Top { __reduce447(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 448 => { - __reduce448(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 449 => { - __reduce449(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 450 => { - // LambdaDef = "lambda", ParameterList, ":", Test<"all"> => ActionFn(1681); - assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); - let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant47(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym3.2; - let __nt = match super::__action1681::<>(mode, __sym0, __sym1, __sym2, __sym3) { - Ok(v) => v, - Err(e) => return Some(Err(e)), - }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 164) - } - 451 => { - // LambdaDef = "lambda", ":", Test<"all"> => ActionFn(1682); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant0(__symbols); + // IpyEscapeCommandExpr = ipy_escape_command => ActionFn(1312); + let __sym0 = __pop_Variant4(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = match super::__action1682::<>(mode, __sym0, __sym1, __sym2) { + let __end = __sym0.2; + let __nt = match super::__action1312::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 164) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 163) } - 452 => { - // LineMagicExpr = line_magic => ActionFn(1308); + 449 => { + // IpyEscapeCommandStatement = ipy_escape_command => ActionFn(1313); let __sym0 = __pop_Variant4(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1308::<>(mode, __sym0) { + let __nt = match super::__action1313::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 165) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 164) } - 453 => { - // LineMagicStatement = line_magic => ActionFn(1309); - let __sym0 = __pop_Variant4(__symbols); + 450 => { + // IpyHelpEndEscapeCommandStatement = Expression<"all">, ("?")+ => ActionFn(1314); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant21(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action1309::<>(mode, __sym0) { + let __end = __sym1.2; + let __nt = match super::__action1314::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 166) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 165) + } + 451 => { + __reduce451(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 452 => { + __reduce452(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 453 => { + __reduce453(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 454 => { __reduce454(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 455 => { - __reduce455(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // LambdaDef = "lambda", ParameterList, ":", Test<"all"> => ActionFn(1688); + assert!(__symbols.len() >= 4); + let __sym3 = __pop_Variant14(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant45(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0; + let __end = __sym3.2; + let __nt = match super::__action1688::<>(mode, __sym0, __sym1, __sym2, __sym3) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 168) } 456 => { - __reduce456(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // LambdaDef = "lambda", ":", Test<"all"> => ActionFn(1689); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = match super::__action1689::<>(mode, __sym0, __sym1, __sym2) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 168) } 457 => { __reduce457(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -13712,16 +13755,7 @@ mod __parse__Top { __reduce462(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 463 => { - // LiteralPattern = (@L string @R)+ => ActionFn(1315); - let __sym0 = __pop_Variant44(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action1315::<>(mode, __sym0) { - Ok(v) => v, - Err(e) => return Some(Err(e)), - }; - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + __reduce463(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 464 => { __reduce464(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -13730,7 +13764,16 @@ mod __parse__Top { __reduce465(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 466 => { - __reduce466(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // LiteralPattern = (@L string @R)+ => ActionFn(1321); + let __sym0 = __pop_Variant42(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = match super::__action1321::<>(mode, __sym0) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } 467 => { __reduce467(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -13742,16 +13785,7 @@ mod __parse__Top { __reduce469(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 470 => { - // MappingKey = (@L string @R)+ => ActionFn(835); - let __sym0 = __pop_Variant44(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = match super::__action835::<>(mode, __sym0) { - Ok(v) => v, - Err(e) => return Some(Err(e)), - }; - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + __reduce470(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 471 => { __reduce471(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -13760,7 +13794,16 @@ mod __parse__Top { __reduce472(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 473 => { - __reduce473(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + // MappingKey = (@L string @R)+ => ActionFn(838); + let __sym0 = __pop_Variant42(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = match super::__action838::<>(mode, __sym0) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } 474 => { __reduce474(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -14003,3021 +14046,3021 @@ mod __parse__Top { __reduce553(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 554 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1561); + __reduce554(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 555 => { + __reduce555(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 556 => { + __reduce556(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 557 => { + __reduce557(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 558 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1568); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1561::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1568::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 555 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1562); + 559 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1569); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1562::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1569::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 556 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1563); + 560 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1570); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1563::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1570::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 210) } - 557 => { - // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter, "," => ActionFn(1564); + 561 => { + // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter, "," => ActionFn(1571); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1564::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1571::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 558 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter, "," => ActionFn(1565); + 562 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter, "," => ActionFn(1572); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1565::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1572::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 559 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter, "," => ActionFn(1566); + 563 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter, "," => ActionFn(1573); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1566::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1573::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 560 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1567); + 564 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1574); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1567::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1574::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 561 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1568); + 565 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1575); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1568::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1575::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 210) } - 562 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1569); + 566 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1576); assert!(__symbols.len() >= 11); let __sym10 = __pop_Variant0(__symbols); - let __sym9 = __pop_Variant10(__symbols); + let __sym9 = __pop_Variant8(__symbols); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym10.2; - let __nt = match super::__action1569::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9, __sym10) { + let __nt = match super::__action1576::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9, __sym10) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (11, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (11, 210) } - 563 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1570); + 567 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1577); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1570::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1577::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 564 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1571); + 568 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1578); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1571::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1578::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 565 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1572); + 569 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1579); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1572::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1579::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 210) } - 566 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, "," => ActionFn(1573); + 570 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, "," => ActionFn(1580); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1573::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1580::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 567 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, "," => ActionFn(1574); + 571 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, "," => ActionFn(1581); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1574::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1581::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 568 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, "," => ActionFn(1575); + 572 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, "," => ActionFn(1582); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1575::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1582::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 569 => { - // ParameterList = OneOrMore>, ",", "*", "," => ActionFn(1576); + 573 => { + // ParameterList = OneOrMore>, ",", "*", "," => ActionFn(1583); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1576::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1583::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 570 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", "," => ActionFn(1577); + 574 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", "," => ActionFn(1584); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1577::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1584::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 571 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", "," => ActionFn(1578); + 575 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", "," => ActionFn(1585); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1578::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1585::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 572 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1579); + 576 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1586); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1579::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1586::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 573 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1580); + 577 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1587); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1580::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1587::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 574 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1581); + 578 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, "," => ActionFn(1588); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1581::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1588::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 575 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, "," => ActionFn(1582); + 579 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, "," => ActionFn(1589); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1582::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1589::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 576 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, "," => ActionFn(1583); + 580 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, "," => ActionFn(1590); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1583::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1590::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 577 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, "," => ActionFn(1584); + 581 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, "," => ActionFn(1591); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1584::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1591::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 578 => { - // ParameterList = OneOrMore>, "," => ActionFn(1585); + 582 => { + // ParameterList = OneOrMore>, "," => ActionFn(1592); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1585::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1592::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 210) } - 579 => { - // ParameterList = OneOrMore>, ",", "/", "," => ActionFn(1586); + 583 => { + // ParameterList = OneOrMore>, ",", "/", "," => ActionFn(1593); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1586::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1593::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 580 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, "," => ActionFn(1587); + 584 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, "," => ActionFn(1594); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1587::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1594::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 581 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1588); + 585 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1595); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1588::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1595::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 582 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1589); + 586 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1596); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1589::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1596::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 583 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1590); + 587 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ",", KwargParameter => ActionFn(1597); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1590::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1597::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 584 => { - // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter => ActionFn(1591); + 588 => { + // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter => ActionFn(1598); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1591::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1598::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 585 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter => ActionFn(1592); + 589 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter => ActionFn(1599); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1592::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1599::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 586 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter => ActionFn(1593); + 590 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter => ActionFn(1600); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1593::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1600::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 587 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1594); + 591 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1601); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1594::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1601::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 588 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1595); + 592 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1602); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1595::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1602::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 589 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1596); + 593 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1603); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant10(__symbols); + let __sym9 = __pop_Variant8(__symbols); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1596::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1603::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 210) } - 590 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1597); + 594 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1604); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1597::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1604::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 591 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1598); + 595 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1605); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1598::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1605::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 592 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1599); + 596 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1606); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1599::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1606::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 210) } - 593 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter => ActionFn(1600); + 597 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter => ActionFn(1607); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1600::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1607::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 594 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter => ActionFn(1601); + 598 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter => ActionFn(1608); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1601::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1608::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 595 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter => ActionFn(1602); + 599 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter => ActionFn(1609); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1602::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1609::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 596 => { - // ParameterList = OneOrMore>, ",", "*" => ActionFn(1603); + 600 => { + // ParameterList = OneOrMore>, ",", "*" => ActionFn(1610); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1603::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1610::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 597 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*" => ActionFn(1604); + 601 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*" => ActionFn(1611); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1604::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1611::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 598 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*" => ActionFn(1605); + 602 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*" => ActionFn(1612); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1605::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1612::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 599 => { - // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1606); + 603 => { + // ParameterList = OneOrMore>, ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1613); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1606::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1613::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 600 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1607); + 604 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1614); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1607::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1614::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 601 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1608); + 605 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarTypedParameter, ("," >)+ => ActionFn(1615); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1608::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1615::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 210) } - 602 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+ => ActionFn(1609); + 606 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+ => ActionFn(1616); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1609::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1616::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 603 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+ => ActionFn(1610); + 607 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+ => ActionFn(1617); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1610::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1617::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 604 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+ => ActionFn(1611); + 608 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+ => ActionFn(1618); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1611::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1618::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 605 => { - // ParameterList = OneOrMore> => ActionFn(1612); - let __sym0 = __pop_Variant81(__symbols); + 609 => { + // ParameterList = OneOrMore> => ActionFn(1619); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1612::<>(mode, __sym0) { + let __nt = match super::__action1619::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 210) } - 606 => { - // ParameterList = OneOrMore>, ",", "/" => ActionFn(1613); + 610 => { + // ParameterList = OneOrMore>, ",", "/" => ActionFn(1620); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1613::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1620::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 607 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+ => ActionFn(1614); + 611 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+ => ActionFn(1621); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1614::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1621::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 608 => { - // ParameterList = OneOrMore>, ",", KwargParameter, "," => ActionFn(1615); + 612 => { + // ParameterList = OneOrMore>, ",", KwargParameter, "," => ActionFn(1622); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1615::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1622::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 609 => { - // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter, "," => ActionFn(1616); + 613 => { + // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter, "," => ActionFn(1623); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1616::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1623::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 610 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter, "," => ActionFn(1617); + 614 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter, "," => ActionFn(1624); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1617::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1624::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 210) } - 611 => { - // ParameterList = OneOrMore>, ",", KwargParameter => ActionFn(1618); + 615 => { + // ParameterList = OneOrMore>, ",", KwargParameter => ActionFn(1625); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1618::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1625::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 612 => { - // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter => ActionFn(1619); + 616 => { + // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter => ActionFn(1626); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1619::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1626::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 613 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter => ActionFn(1620); + 617 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter => ActionFn(1627); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1620::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1627::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 614 => { - // ParameterList = "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1358); + 618 => { + // ParameterList = "*", StarTypedParameter, ",", KwargParameter, "," => ActionFn(1365); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1358::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1365::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 615 => { - // ParameterList = "*", ",", KwargParameter, "," => ActionFn(1359); + 619 => { + // ParameterList = "*", ",", KwargParameter, "," => ActionFn(1366); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1359::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1366::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 616 => { - // ParameterList = "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1360); + 620 => { + // ParameterList = "*", StarTypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1367); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1360::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1367::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 210) } - 617 => { - // ParameterList = "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1361); + 621 => { + // ParameterList = "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1368); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1361::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1368::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 618 => { - // ParameterList = "*", StarTypedParameter, "," => ActionFn(1362); + 622 => { + // ParameterList = "*", StarTypedParameter, "," => ActionFn(1369); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1362::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1369::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 619 => { - // ParameterList = "*", "," => ActionFn(1363); + 623 => { + // ParameterList = "*", "," => ActionFn(1370); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1363::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1370::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 210) } - 620 => { - // ParameterList = "*", StarTypedParameter, ("," >)+, "," => ActionFn(1364); + 624 => { + // ParameterList = "*", StarTypedParameter, ("," >)+, "," => ActionFn(1371); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1364::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1371::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 621 => { - // ParameterList = "*", ("," >)+, "," => ActionFn(1365); + 625 => { + // ParameterList = "*", ("," >)+, "," => ActionFn(1372); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1365::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1372::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 622 => { - // ParameterList = "*", StarTypedParameter, ",", KwargParameter => ActionFn(1366); + 626 => { + // ParameterList = "*", StarTypedParameter, ",", KwargParameter => ActionFn(1373); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1366::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1373::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 623 => { - // ParameterList = "*", ",", KwargParameter => ActionFn(1367); + 627 => { + // ParameterList = "*", ",", KwargParameter => ActionFn(1374); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1367::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1374::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 624 => { - // ParameterList = "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1368); + 628 => { + // ParameterList = "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1375); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1368::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1375::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 210) } - 625 => { - // ParameterList = "*", ("," >)+, ",", KwargParameter => ActionFn(1369); + 629 => { + // ParameterList = "*", ("," >)+, ",", KwargParameter => ActionFn(1376); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1369::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1376::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 210) } - 626 => { - // ParameterList = "*", StarTypedParameter => ActionFn(1370); + 630 => { + // ParameterList = "*", StarTypedParameter => ActionFn(1377); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1370::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1377::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 210) } - 627 => { - // ParameterList = "*" => ActionFn(1371); + 631 => { + // ParameterList = "*" => ActionFn(1378); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1371::<>(mode, __sym0) { + let __nt = match super::__action1378::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 210) } - 628 => { - // ParameterList = "*", StarTypedParameter, ("," >)+ => ActionFn(1372); + 632 => { + // ParameterList = "*", StarTypedParameter, ("," >)+ => ActionFn(1379); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1372::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1379::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 210) } - 629 => { - // ParameterList = "*", ("," >)+ => ActionFn(1373); + 633 => { + // ParameterList = "*", ("," >)+ => ActionFn(1380); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1373::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1380::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 207) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 210) } - 630 => { - __reduce630(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 634 => { + __reduce634(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 631 => { - __reduce631(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 635 => { + __reduce635(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 632 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1621); + 636 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1628); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1621::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1628::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 633 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1622); + 637 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1629); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1622::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1629::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 634 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1623); + 638 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1630); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1623::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1630::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 211) } - 635 => { - // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter, "," => ActionFn(1624); + 639 => { + // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter, "," => ActionFn(1631); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1624::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1631::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 636 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter, "," => ActionFn(1625); + 640 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter, "," => ActionFn(1632); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1625::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1632::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 637 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter, "," => ActionFn(1626); + 641 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter, "," => ActionFn(1633); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1626::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1633::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 638 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1627); + 642 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1634); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1627::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1634::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 639 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1628); + 643 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1635); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1628::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1635::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 211) } - 640 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1629); + 644 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1636); assert!(__symbols.len() >= 11); let __sym10 = __pop_Variant0(__symbols); - let __sym9 = __pop_Variant10(__symbols); + let __sym9 = __pop_Variant8(__symbols); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym10.2; - let __nt = match super::__action1629::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9, __sym10) { + let __nt = match super::__action1636::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9, __sym10) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (11, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (11, 211) } - 641 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1630); + 645 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1637); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1630::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1637::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 642 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1631); + 646 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1638); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1631::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1638::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 643 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1632); + 647 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1639); assert!(__symbols.len() >= 10); let __sym9 = __pop_Variant0(__symbols); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1632::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1639::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 211) } - 644 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, "," => ActionFn(1633); + 648 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, "," => ActionFn(1640); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1633::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1640::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 645 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, "," => ActionFn(1634); + 649 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, "," => ActionFn(1641); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1634::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1641::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 646 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, "," => ActionFn(1635); + 650 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, "," => ActionFn(1642); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1635::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1642::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 647 => { - // ParameterList = OneOrMore>, ",", "*", "," => ActionFn(1636); + 651 => { + // ParameterList = OneOrMore>, ",", "*", "," => ActionFn(1643); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1636::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1643::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 648 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", "," => ActionFn(1637); + 652 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", "," => ActionFn(1644); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1637::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1644::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 649 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", "," => ActionFn(1638); + 653 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", "," => ActionFn(1645); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1638::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1645::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 650 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1639); + 654 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1646); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1639::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1646::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 651 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1640); + 655 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1647); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1640::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1647::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 652 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1641); + 656 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1648); assert!(__symbols.len() >= 9); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1641::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1648::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 653 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, "," => ActionFn(1642); + 657 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, "," => ActionFn(1649); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1642::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1649::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 654 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, "," => ActionFn(1643); + 658 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, "," => ActionFn(1650); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1643::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1650::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 655 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, "," => ActionFn(1644); + 659 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, "," => ActionFn(1651); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1644::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1651::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 656 => { - // ParameterList = OneOrMore>, "," => ActionFn(1645); + 660 => { + // ParameterList = OneOrMore>, "," => ActionFn(1652); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1645::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1652::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 211) } - 657 => { - // ParameterList = OneOrMore>, ",", "/", "," => ActionFn(1646); + 661 => { + // ParameterList = OneOrMore>, ",", "/", "," => ActionFn(1653); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1646::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1653::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 658 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, "," => ActionFn(1647); + 662 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, "," => ActionFn(1654); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1647::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1654::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 659 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1648); + 663 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1655); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1648::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1655::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 660 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1649); + 664 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1656); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1649::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1656::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 661 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1650); + 665 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1657); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1650::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1657::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 662 => { - // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter => ActionFn(1651); + 666 => { + // ParameterList = OneOrMore>, ",", "*", ",", KwargParameter => ActionFn(1658); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1651::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1658::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 663 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter => ActionFn(1652); + 667 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ",", KwargParameter => ActionFn(1659); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1652::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1659::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 664 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter => ActionFn(1653); + 668 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ",", KwargParameter => ActionFn(1660); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1653::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1660::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 665 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1654); + 669 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1661); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant10(__symbols); + let __sym6 = __pop_Variant8(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1654::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1661::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 666 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1655); + 670 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1662); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1655::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1662::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 667 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1656); + 671 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1663); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant10(__symbols); + let __sym9 = __pop_Variant8(__symbols); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = match super::__action1656::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { + let __nt = match super::__action1663::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (10, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (10, 211) } - 668 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1657); + 672 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1664); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1657::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1664::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 669 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1658); + 673 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1665); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant10(__symbols); + let __sym7 = __pop_Variant8(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1658::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1665::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 670 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1659); + 674 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+, ",", KwargParameter => ActionFn(1666); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant10(__symbols); + let __sym8 = __pop_Variant8(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = match super::__action1659::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { + let __nt = match super::__action1666::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (9, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (9, 211) } - 671 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter => ActionFn(1660); + 675 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter => ActionFn(1667); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant64(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1660::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1667::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 672 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter => ActionFn(1661); + 676 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter => ActionFn(1668); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant64(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1661::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1668::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 673 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter => ActionFn(1662); + 677 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter => ActionFn(1669); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1662::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1669::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 674 => { - // ParameterList = OneOrMore>, ",", "*" => ActionFn(1663); + 678 => { + // ParameterList = OneOrMore>, ",", "*" => ActionFn(1670); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1663::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1670::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 675 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*" => ActionFn(1664); + 679 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*" => ActionFn(1671); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1664::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1671::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 676 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*" => ActionFn(1665); + 680 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*" => ActionFn(1672); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1665::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1672::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 677 => { - // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1666); + 681 => { + // ParameterList = OneOrMore>, ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1673); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant13(__symbols); - let __sym3 = __pop_Variant64(__symbols); + let __sym4 = __pop_Variant11(__symbols); + let __sym3 = __pop_Variant63(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1666::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1673::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 678 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1667); + 682 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1674); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant13(__symbols); - let __sym5 = __pop_Variant64(__symbols); + let __sym6 = __pop_Variant11(__symbols); + let __sym5 = __pop_Variant63(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1667::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1674::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 679 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1668); + 683 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", StarUntypedParameter, ("," >)+ => ActionFn(1675); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant13(__symbols); - let __sym6 = __pop_Variant64(__symbols); + let __sym7 = __pop_Variant11(__symbols); + let __sym6 = __pop_Variant63(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = match super::__action1668::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { + let __nt = match super::__action1675::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (8, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (8, 211) } - 680 => { - // ParameterList = OneOrMore>, ",", "*", ("," >)+ => ActionFn(1669); + 684 => { + // ParameterList = OneOrMore>, ",", "*", ("," >)+ => ActionFn(1676); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1669::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1676::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 681 => { - // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+ => ActionFn(1670); + 685 => { + // ParameterList = OneOrMore>, ",", "/", ",", "*", ("," >)+ => ActionFn(1677); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant13(__symbols); + let __sym5 = __pop_Variant11(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1670::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1677::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 682 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+ => ActionFn(1671); + 686 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", "*", ("," >)+ => ActionFn(1678); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant13(__symbols); + let __sym6 = __pop_Variant11(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1671::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1678::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 683 => { - // ParameterList = OneOrMore> => ActionFn(1672); - let __sym0 = __pop_Variant81(__symbols); + 687 => { + // ParameterList = OneOrMore> => ActionFn(1679); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1672::<>(mode, __sym0) { + let __nt = match super::__action1679::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 211) } - 684 => { - // ParameterList = OneOrMore>, ",", "/" => ActionFn(1673); + 688 => { + // ParameterList = OneOrMore>, ",", "/" => ActionFn(1680); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1673::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1680::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 685 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+ => ActionFn(1674); + 689 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+ => ActionFn(1681); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1674::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1681::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 686 => { - // ParameterList = OneOrMore>, ",", KwargParameter, "," => ActionFn(1675); + 690 => { + // ParameterList = OneOrMore>, ",", KwargParameter, "," => ActionFn(1682); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1675::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1682::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 687 => { - // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter, "," => ActionFn(1676); + 691 => { + // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter, "," => ActionFn(1683); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1676::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1683::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 688 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter, "," => ActionFn(1677); + 692 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter, "," => ActionFn(1684); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = match super::__action1677::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { + let __nt = match super::__action1684::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (7, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (7, 211) } - 689 => { - // ParameterList = OneOrMore>, ",", KwargParameter => ActionFn(1678); + 693 => { + // ParameterList = OneOrMore>, ",", KwargParameter => ActionFn(1685); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1678::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1685::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 690 => { - // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter => ActionFn(1679); + 694 => { + // ParameterList = OneOrMore>, ",", "/", ",", KwargParameter => ActionFn(1686); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1679::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1686::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 691 => { - // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter => ActionFn(1680); + 695 => { + // ParameterList = OneOrMore>, ",", "/", ("," >)+, ",", KwargParameter => ActionFn(1687); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant10(__symbols); + let __sym5 = __pop_Variant8(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1680::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1687::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 692 => { - // ParameterList = "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1396); + 696 => { + // ParameterList = "*", StarUntypedParameter, ",", KwargParameter, "," => ActionFn(1403); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1396::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1403::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 693 => { - // ParameterList = "*", ",", KwargParameter, "," => ActionFn(1397); + 697 => { + // ParameterList = "*", ",", KwargParameter, "," => ActionFn(1404); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1397::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1404::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 694 => { - // ParameterList = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1398); + 698 => { + // ParameterList = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter, "," => ActionFn(1405); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = match super::__action1398::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { + let __nt = match super::__action1405::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (6, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (6, 211) } - 695 => { - // ParameterList = "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1399); + 699 => { + // ParameterList = "*", ("," >)+, ",", KwargParameter, "," => ActionFn(1406); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1399::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1406::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 696 => { - // ParameterList = "*", StarUntypedParameter, "," => ActionFn(1400); + 700 => { + // ParameterList = "*", StarUntypedParameter, "," => ActionFn(1407); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1400::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1407::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 697 => { - // ParameterList = "*", "," => ActionFn(1401); + 701 => { + // ParameterList = "*", "," => ActionFn(1408); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1401::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1408::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 211) } - 698 => { - // ParameterList = "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1402); + 702 => { + // ParameterList = "*", StarUntypedParameter, ("," >)+, "," => ActionFn(1409); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1402::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1409::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 699 => { - // ParameterList = "*", ("," >)+, "," => ActionFn(1403); + 703 => { + // ParameterList = "*", ("," >)+, "," => ActionFn(1410); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1403::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1410::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 700 => { - // ParameterList = "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1404); + 704 => { + // ParameterList = "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1411); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1404::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1411::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 701 => { - // ParameterList = "*", ",", KwargParameter => ActionFn(1405); + 705 => { + // ParameterList = "*", ",", KwargParameter => ActionFn(1412); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1405::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1412::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 702 => { - // ParameterList = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1406); + 706 => { + // ParameterList = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1413); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1406::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1413::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (5, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (5, 211) } - 703 => { - // ParameterList = "*", ("," >)+, ",", KwargParameter => ActionFn(1407); + 707 => { + // ParameterList = "*", ("," >)+, ",", KwargParameter => ActionFn(1414); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1407::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1414::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (4, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (4, 211) } - 704 => { - // ParameterList = "*", StarUntypedParameter => ActionFn(1408); + 708 => { + // ParameterList = "*", StarUntypedParameter => ActionFn(1415); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1408::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1415::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 211) } - 705 => { - // ParameterList = "*" => ActionFn(1409); + 709 => { + // ParameterList = "*" => ActionFn(1416); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1409::<>(mode, __sym0) { + let __nt = match super::__action1416::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 211) } - 706 => { - // ParameterList = "*", StarUntypedParameter, ("," >)+ => ActionFn(1410); + 710 => { + // ParameterList = "*", StarUntypedParameter, ("," >)+ => ActionFn(1417); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1410::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1417::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 211) } - 707 => { - // ParameterList = "*", ("," >)+ => ActionFn(1411); + 711 => { + // ParameterList = "*", ("," >)+ => ActionFn(1418); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1411::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1418::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 208) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 211) } - 708 => { - __reduce708(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 712 => { + __reduce712(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 709 => { - __reduce709(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 713 => { + __reduce713(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 710 => { - __reduce710(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 714 => { + __reduce714(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 711 => { - __reduce711(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + 715 => { + __reduce715(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } - 712 => { - // ParameterListStarArgs = "*", StarTypedParameter, ",", KwargParameter => ActionFn(874); + 716 => { + // ParameterListStarArgs = "*", StarTypedParameter, ",", KwargParameter => ActionFn(878); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action874::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action878::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 213) } - 713 => { - // ParameterListStarArgs = "*", ",", KwargParameter => ActionFn(875); + 717 => { + // ParameterListStarArgs = "*", ",", KwargParameter => ActionFn(879); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action875::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action879::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 213) } - 714 => { - // ParameterListStarArgs = "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(876); + 718 => { + // ParameterListStarArgs = "*", StarTypedParameter, ("," >)+, ",", KwargParameter => ActionFn(880); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action876::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action880::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 213) } - 715 => { - // ParameterListStarArgs = "*", ("," >)+, ",", KwargParameter => ActionFn(877); + 719 => { + // ParameterListStarArgs = "*", ("," >)+, ",", KwargParameter => ActionFn(881); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action877::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action881::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 213) } - 716 => { - // ParameterListStarArgs = "*", StarTypedParameter => ActionFn(878); + 720 => { + // ParameterListStarArgs = "*", StarTypedParameter => ActionFn(882); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action878::<>(mode, __sym0, __sym1) { + let __nt = match super::__action882::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 213) } - 717 => { - // ParameterListStarArgs = "*" => ActionFn(879); + 721 => { + // ParameterListStarArgs = "*" => ActionFn(883); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action879::<>(mode, __sym0) { + let __nt = match super::__action883::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (1, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (1, 213) } - 718 => { - // ParameterListStarArgs = "*", StarTypedParameter, ("," >)+ => ActionFn(880); + 722 => { + // ParameterListStarArgs = "*", StarTypedParameter, ("," >)+ => ActionFn(884); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action880::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action884::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 213) } - 719 => { - // ParameterListStarArgs = "*", ("," >)+ => ActionFn(881); + 723 => { + // ParameterListStarArgs = "*", ("," >)+ => ActionFn(885); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action881::<>(mode, __sym0, __sym1) { + let __nt = match super::__action885::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 210) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 213) } - 720 => { - // ParameterListStarArgs = "*", StarUntypedParameter, ",", KwargParameter => ActionFn(999); + 724 => { + // ParameterListStarArgs = "*", StarUntypedParameter, ",", KwargParameter => ActionFn(1001); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action999::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1001::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 214) } - 721 => { - // ParameterListStarArgs = "*", ",", KwargParameter => ActionFn(1000); + 725 => { + // ParameterListStarArgs = "*", ",", KwargParameter => ActionFn(1002); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant8(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1000::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1002::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 214) } - 722 => { - // ParameterListStarArgs = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1001); + 726 => { + // ParameterListStarArgs = "*", StarUntypedParameter, ("," >)+, ",", KwargParameter => ActionFn(1003); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant8(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = match super::__action1001::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { + let __nt = match super::__action1003::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (5, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (5, 214) } - 723 => { - // ParameterListStarArgs = "*", ("," >)+, ",", KwargParameter => ActionFn(1002); + 727 => { + // ParameterListStarArgs = "*", ("," >)+, ",", KwargParameter => ActionFn(1004); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant8(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = match super::__action1002::<>(mode, __sym0, __sym1, __sym2, __sym3) { + let __nt = match super::__action1004::<>(mode, __sym0, __sym1, __sym2, __sym3) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (4, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (4, 214) } - 724 => { - // ParameterListStarArgs = "*", StarUntypedParameter => ActionFn(1003); + 728 => { + // ParameterListStarArgs = "*", StarUntypedParameter => ActionFn(1005); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1003::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1005::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 214) } - 725 => { - // ParameterListStarArgs = "*" => ActionFn(1004); + 729 => { + // ParameterListStarArgs = "*" => ActionFn(1006); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = match super::__action1004::<>(mode, __sym0) { + let __nt = match super::__action1006::<>(mode, __sym0) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (1, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (1, 214) } - 726 => { - // ParameterListStarArgs = "*", StarUntypedParameter, ("," >)+ => ActionFn(1005); + 730 => { + // ParameterListStarArgs = "*", StarUntypedParameter, ("," >)+ => ActionFn(1007); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant13(__symbols); - let __sym1 = __pop_Variant64(__symbols); + let __sym2 = __pop_Variant11(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1005::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1007::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (3, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (3, 214) } - 727 => { - // ParameterListStarArgs = "*", ("," >)+ => ActionFn(1006); + 731 => { + // ParameterListStarArgs = "*", ("," >)+ => ActionFn(1008); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant13(__symbols); + let __sym1 = __pop_Variant11(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1006::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1008::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant14(__nt), __end)); - (2, 211) + __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + (2, 214) } - 728 => { - // Parameters = "(", ParameterList, ")" => ActionFn(1501); + 732 => { + // Parameters = "(", ParameterList, ")" => ActionFn(1506); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant47(__symbols); + let __sym1 = __pop_Variant45(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = match super::__action1501::<>(mode, __sym0, __sym1, __sym2) { + let __nt = match super::__action1506::<>(mode, __sym0, __sym1, __sym2) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (3, 212) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (3, 215) } - 729 => { - // Parameters = "(", ")" => ActionFn(1502); + 733 => { + // Parameters = "(", ")" => ActionFn(1507); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = match super::__action1502::<>(mode, __sym0, __sym1) { + let __nt = match super::__action1507::<>(mode, __sym0, __sym1) { Ok(v) => v, Err(e) => return Some(Err(e)), }; - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 212) - } - 730 => { - __reduce730(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 731 => { - __reduce731(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 732 => { - __reduce732(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) - } - 733 => { - __reduce733(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 215) } 734 => { __reduce734(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) @@ -17566,8 +17609,23 @@ mod __parse__Top { __reduce915(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) } 916 => { + __reduce916(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 917 => { + __reduce917(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 918 => { + __reduce918(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 919 => { + __reduce919(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 920 => { + __reduce920(mode, __lookahead_start, __symbols, core::marker::PhantomData::<()>) + } + 921 => { // __Top = Top => ActionFn(0); - let __sym0 = __pop_Variant90(__symbols); + let __sym0 = __pop_Variant89(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action0::<>(mode, __sym0); @@ -17589,50 +17647,50 @@ mod __parse__Top { fn __pop_Variant4< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (MagicKind, String), TextSize) + ) -> (TextSize, (IpyEscapeKind, String), TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant4(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant32< + fn __pop_Variant30< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant32(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant30(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant14< + fn __pop_Variant59< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (Option>, Vec, Option>), TextSize) + ) -> (TextSize, (Option>, ast::Expr), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant14(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant59(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant60< + fn __pop_Variant12< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (Option>, ast::Expr), TextSize) + ) -> (TextSize, (Option>, Vec, Option>), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant60(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant12(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant73< + fn __pop_Variant72< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (Option, Option), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant73(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant72(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } @@ -17646,93 +17704,93 @@ mod __parse__Top { _ => __symbol_type_mismatch() } } - fn __pop_Variant43< + fn __pop_Variant41< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (TextSize, (String, StringKind, bool), TextSize), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant43(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant41(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant28< + fn __pop_Variant26< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (TextSize, ast::Expr, ast::Suite), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant28(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant26(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant30< + fn __pop_Variant28< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (TextSize, ast::Suite), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant30(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant28(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant83< + fn __pop_Variant82< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (Vec, Vec), TextSize) + ) -> (TextSize, (Vec, Vec), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant83(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant82(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant45< + fn __pop_Variant43< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (ast::CmpOp, ast::Expr), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant45(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant43(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant61< + fn __pop_Variant60< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (ast::Expr, ast::Expr), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant61(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant60(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant40< + fn __pop_Variant38< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (ast::Expr, ast::Identifier), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant40(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant38(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant77< + fn __pop_Variant76< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (ast::Expr, ast::Pattern), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant77(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant76(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant76< + fn __pop_Variant75< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (ast::Identifier, ast::Pattern), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant76(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant75(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } @@ -17746,33 +17804,13 @@ mod __parse__Top { _ => __symbol_type_mismatch() } } - fn __pop_Variant8< - >( - __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, (token::Tok, ArgumentList, token::Tok), TextSize) - { - match __symbols.pop() { - Some((__l, __Symbol::Variant8(__v), __r)) => (__l, __v, __r), - _ => __symbol_type_mismatch() - } - } - fn __pop_Variant21< + fn __pop_Variant19< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, (token::Tok, ast::Identifier), TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant21(__v), __r)) => (__l, __v, __r), - _ => __symbol_type_mismatch() - } - } - fn __pop_Variant51< - >( - __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ArgumentList, TextSize) - { - match __symbols.pop() { - Some((__l, __Symbol::Variant51(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant19(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } @@ -17786,23 +17824,23 @@ mod __parse__Top { _ => __symbol_type_mismatch() } } - fn __pop_Variant10< + fn __pop_Variant8< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, Option>, TextSize) + ) -> (TextSize, Option>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant10(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant8(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant87< + fn __pop_Variant86< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant87(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant86(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } @@ -17816,490 +17854,510 @@ mod __parse__Top { _ => __symbol_type_mismatch() } } - fn __pop_Variant49< + fn __pop_Variant47< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, TextSize, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant49(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant47(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant52< + fn __pop_Variant51< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant52(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant51(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant62< + fn __pop_Variant61< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec<(Option>, ast::Expr)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant62(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant61(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant80< + fn __pop_Variant79< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec<(ast::Expr, ast::Pattern)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant80(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant79(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant79< + fn __pop_Variant78< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec<(ast::Identifier, ast::Pattern)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant79(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant78(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant70< + fn __pop_Variant69< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant70(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant69(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant81< + fn __pop_Variant53< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, Vec, TextSize) + ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant81(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant53(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant54< + fn __pop_Variant32< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, Vec, TextSize) + ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant54(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant32(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant34< + fn __pop_Variant77< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, Vec, TextSize) + ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant34(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant77(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant78< + fn __pop_Variant80< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, Vec, TextSize) + ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant78(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant80(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant53< + fn __pop_Variant52< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant53(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant52(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant89< + fn __pop_Variant88< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant89(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant88(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant82< + fn __pop_Variant81< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant82(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant81(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant41< + fn __pop_Variant39< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant41(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant39(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant33< + fn __pop_Variant31< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant33(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant31(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant44< + fn __pop_Variant42< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant44(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant42(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant29< + fn __pop_Variant27< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec<(TextSize, ast::Expr, ast::Suite)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant29(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant27(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant46< + fn __pop_Variant44< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec<(ast::CmpOp, ast::Expr)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant46(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant44(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant22< + fn __pop_Variant20< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec<(token::Tok, ast::Identifier)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant22(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant20(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant13< + fn __pop_Variant85< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant13(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant85(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant86< + fn __pop_Variant58< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant86(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant58(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant59< + fn __pop_Variant66< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant59(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant66(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant67< + fn __pop_Variant16< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant67(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant16(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant18< + fn __pop_Variant71< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant18(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant71(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant72< + fn __pop_Variant74< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant72(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant74(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant75< + fn __pop_Variant11< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, alloc::vec::Vec, TextSize) + ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant75(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant11(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant37< + fn __pop_Variant35< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant37(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant35(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant39< + fn __pop_Variant37< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant39(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant37(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant20< + fn __pop_Variant18< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant20(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant18(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant23< + fn __pop_Variant21< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, alloc::vec::Vec, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant23(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant21(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant69< + fn __pop_Variant68< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::Alias, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant69(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant68(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant64< + fn __pop_Variant49< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Arg, TextSize) + ) -> (TextSize, ast::Arguments, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant64(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant49(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant12< + fn __pop_Variant55< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::ArgWithDefault, TextSize) + ) -> (TextSize, ast::CmpOp, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant12(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant55(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant47< + fn __pop_Variant84< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Arguments, TextSize) + ) -> (TextSize, ast::Comprehension, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant47(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant84(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } fn __pop_Variant56< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::CmpOp, TextSize) + ) -> (TextSize, ast::Constant, TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant56(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant85< + fn __pop_Variant57< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Comprehension, TextSize) + ) -> (TextSize, ast::Decorator, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant85(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant57(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant57< + fn __pop_Variant65< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Constant, TextSize) + ) -> (TextSize, ast::ExceptHandler, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant57(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant65(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant58< + fn __pop_Variant14< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Decorator, TextSize) + ) -> (TextSize, ast::Expr, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant58(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant14(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant66< + fn __pop_Variant22< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::ExceptHandler, TextSize) + ) -> (TextSize, ast::Identifier, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant66(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant22(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant16< + fn __pop_Variant70< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Expr, TextSize) + ) -> (TextSize, ast::Int, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant16(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant70(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant24< + fn __pop_Variant73< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Identifier, TextSize) + ) -> (TextSize, ast::MatchCase, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant24(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant73(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant71< + fn __pop_Variant89< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Int, TextSize) + ) -> (TextSize, ast::Mod, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant71(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant89(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant74< + fn __pop_Variant48< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::MatchCase, TextSize) + ) -> (TextSize, ast::Operator, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant74(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant48(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant90< + fn __pop_Variant63< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Mod, TextSize) + ) -> (TextSize, ast::Parameter, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant90(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant63(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant50< + fn __pop_Variant10< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, ast::Operator, TextSize) + ) -> (TextSize, ast::ParameterWithDefault, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant50(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant10(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant36< + fn __pop_Variant45< + >( + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> + ) -> (TextSize, ast::Parameters, TextSize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant45(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant34< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::Pattern, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant36(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant34(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant38< + fn __pop_Variant36< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::Stmt, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant38(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant36(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant26< + fn __pop_Variant24< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::Suite, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant26(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant24(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant91< + fn __pop_Variant90< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::TypeParam, TextSize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant90(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant91< + >( + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> + ) -> (TextSize, ast::TypeParams, TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant91(__v), __r)) => (__l, __v, __r), @@ -18316,183 +18374,183 @@ mod __parse__Top { _ => __symbol_type_mismatch() } } - fn __pop_Variant19< + fn __pop_Variant17< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, ast::WithItem, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant19(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant17(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant68< + fn __pop_Variant67< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, core::option::Option<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant68(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant67(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant15< + fn __pop_Variant13< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize) + ) -> (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant15(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant13(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant31< + fn __pop_Variant29< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> ) -> (TextSize, core::option::Option<(TextSize, ast::Suite)>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant31(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant29(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } fn __pop_Variant9< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option<(token::Tok, ArgumentList, token::Tok)>, TextSize) + ) -> (TextSize, core::option::Option>>, TextSize) { match __symbols.pop() { Some((__l, __Symbol::Variant9(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant11< + fn __pop_Variant87< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>>, TextSize) + ) -> (TextSize, core::option::Option>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant11(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant87(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant88< + fn __pop_Variant62< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, TextSize) + ) -> (TextSize, core::option::Option>, ast::Expr)>>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant88(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant62(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant63< + fn __pop_Variant54< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, ast::Expr)>>, TextSize) + ) -> (TextSize, core::option::Option>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant63(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant54(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant55< + fn __pop_Variant33< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, TextSize) + ) -> (TextSize, core::option::Option>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant55(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant33(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant35< + fn __pop_Variant40< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, TextSize) + ) -> (TextSize, core::option::Option>, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant35(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant40(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant92< + fn __pop_Variant50< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant92(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant50(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant42< + fn __pop_Variant15< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option>, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant42(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant15(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant65< + fn __pop_Variant23< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant65(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant23(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant48< + fn __pop_Variant64< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant48(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant64(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant17< + fn __pop_Variant46< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant17(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant46(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant25< + fn __pop_Variant83< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant25(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant83(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant84< + fn __pop_Variant25< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant84(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant25(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } - fn __pop_Variant27< + fn __pop_Variant92< >( __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)> - ) -> (TextSize, core::option::Option, TextSize) + ) -> (TextSize, core::option::Option, TextSize) { match __symbols.pop() { - Some((__l, __Symbol::Variant27(__v), __r)) => (__l, __v, __r), + Some((__l, __Symbol::Variant92(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } @@ -18534,11 +18592,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ","? = "," => ActionFn(357); + // ","? = "," => ActionFn(362); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action357::<>(mode, __sym0); + let __nt = super::__action362::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); (1, 0) } @@ -18550,10 +18608,10 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ","? = => ActionFn(358); + // ","? = => ActionFn(363); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action358::<>(mode, &__start, &__end); + let __nt = super::__action363::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); (0, 0) } @@ -18565,11 +18623,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ";"? = ";" => ActionFn(381); + // ";"? = ";" => ActionFn(386); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action381::<>(mode, __sym0); + let __nt = super::__action386::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); (1, 1) } @@ -18581,10 +18639,10 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ";"? = => ActionFn(382); + // ";"? = => ActionFn(387); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action382::<>(mode, &__start, &__end); + let __nt = super::__action387::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant7(__nt), __end)); (0, 1) } @@ -18627,16 +18685,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("(" ArgumentList ")") = "(", ArgumentList, ")" => ActionFn(268); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant51(__symbols); + // ("," >) = ",", KwargParameter => ActionFn(418); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant8(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action268::<>(mode, __sym0, __sym1, __sym2); + let __end = __sym1.2; + let __nt = super::__action418::<>(mode, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant8(__nt), __end)); - (3, 3) + (2, 3) } pub(crate) fn __reduce7< >( @@ -18646,16 +18703,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("(" ArgumentList ")")? = "(", ArgumentList, ")" => ActionFn(664); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant51(__symbols); + // ("," >)? = ",", KwargParameter => ActionFn(669); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant8(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action664::<>(mode, __sym0, __sym1, __sym2); + let __end = __sym1.2; + let __nt = super::__action669::<>(mode, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant9(__nt), __end)); - (3, 4) + (2, 4) } pub(crate) fn __reduce8< >( @@ -18665,10 +18721,10 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("(" ArgumentList ")")? = => ActionFn(267); + // ("," >)? = => ActionFn(469); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action267::<>(mode, &__start, &__end); + let __nt = super::__action469::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant9(__nt), __end)); (0, 4) } @@ -18680,14 +18736,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", KwargParameter => ActionFn(411); + // ("," >) = ",", KwargParameter => ActionFn(426); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant10(__symbols); + let __sym1 = __pop_Variant8(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action411::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + let __nt = super::__action426::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); (2, 5) } pub(crate) fn __reduce10< @@ -18698,14 +18754,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = ",", KwargParameter => ActionFn(667); + // ("," >)? = ",", KwargParameter => ActionFn(674); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant10(__symbols); + let __sym1 = __pop_Variant8(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action667::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + let __nt = super::__action674::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); (2, 6) } pub(crate) fn __reduce11< @@ -18716,11 +18772,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = => ActionFn(466); + // ("," >)? = => ActionFn(458); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action466::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + let __nt = super::__action458::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); (0, 6) } pub(crate) fn __reduce12< @@ -18731,13 +18787,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", KwargParameter => ActionFn(419); + // ("," >) = ",", ParameterDef => ActionFn(472); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant10(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action419::<>(mode, __sym0, __sym1); + let __nt = super::__action472::<>(mode, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant10(__nt), __end)); (2, 7) } @@ -18749,15 +18805,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = ",", KwargParameter => ActionFn(672); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant10(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action672::<>(mode, __sym0, __sym1); + // ("," >)* = => ActionFn(470); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action470::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant11(__nt), __end)); - (2, 8) + (0, 8) } pub(crate) fn __reduce14< >( @@ -18767,12 +18820,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = => ActionFn(455); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action455::<>(mode, &__start, &__end); + // ("," >)* = ("," >)+ => ActionFn(471); + let __sym0 = __pop_Variant11(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action471::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant11(__nt), __end)); - (0, 8) + (1, 8) } pub(crate) fn __reduce15< >( @@ -18782,14 +18836,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", ParameterDef => ActionFn(469); + // ("," >)+ = ",", ParameterDef => ActionFn(679); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant12(__symbols); + let __sym1 = __pop_Variant10(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action469::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + let __nt = super::__action679::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); (2, 9) } pub(crate) fn __reduce16< @@ -18800,12 +18854,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = => ActionFn(467); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action467::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (0, 10) + // ("," >)+ = ("," >)+, ",", ParameterDef => ActionFn(680); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant10(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant11(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action680::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + (3, 9) } pub(crate) fn __reduce17< >( @@ -18815,13 +18873,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = ("," >)+ => ActionFn(468); - let __sym0 = __pop_Variant13(__symbols); + // ("," >) = ",", ParameterDef => ActionFn(461); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant10(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action468::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (1, 10) + let __end = __sym1.2; + let __nt = super::__action461::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (2, 10) } pub(crate) fn __reduce18< >( @@ -18831,15 +18891,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ",", ParameterDef => ActionFn(677); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant12(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action677::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (2, 11) + // ("," >)* = => ActionFn(459); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action459::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + (0, 11) } pub(crate) fn __reduce19< >( @@ -18849,16 +18906,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ("," >)+, ",", ParameterDef => ActionFn(678); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant12(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant13(__symbols); + // ("," >)* = ("," >)+ => ActionFn(460); + let __sym0 = __pop_Variant11(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action678::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (3, 11) + let __end = __sym0.2; + let __nt = super::__action460::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + (1, 11) } pub(crate) fn __reduce20< >( @@ -18868,14 +18922,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", ParameterDef => ActionFn(458); + // ("," >)+ = ",", ParameterDef => ActionFn(687); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant12(__symbols); + let __sym1 = __pop_Variant10(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action458::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); + let __nt = super::__action687::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); (2, 12) } pub(crate) fn __reduce21< @@ -18886,14 +18940,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = => ActionFn(456); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action456::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (0, 13) + // ("," >)+ = ("," >)+, ",", ParameterDef => ActionFn(688); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant10(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant11(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action688::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant11(__nt), __end)); + (3, 12) } - pub(crate) fn __reduce22< + pub(crate) fn __reduce38< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -18901,15 +18959,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = ("," >)+ => ActionFn(457); - let __sym0 = __pop_Variant13(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action457::<>(mode, __sym0); + // ("," >)? = => ActionFn(421); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action421::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (1, 13) + (0, 14) } - pub(crate) fn __reduce23< + pub(crate) fn __reduce55< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -18917,17 +18974,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ",", ParameterDef => ActionFn(685); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant12(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action685::<>(mode, __sym0, __sym1); + // ("," >)? = => ActionFn(429); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action429::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (2, 14) + (0, 16) } - pub(crate) fn __reduce24< + pub(crate) fn __reduce56< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -18935,18 +18989,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ("," >)+, ",", ParameterDef => ActionFn(686); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant12(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant13(__symbols); + // ("," >) = ",", Test<"all"> => ActionFn(356); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action686::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant13(__nt), __end)); - (3, 14) + let __end = __sym1.2; + let __nt = super::__action356::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 17) } - pub(crate) fn __reduce41< + pub(crate) fn __reduce57< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -18954,12 +19007,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = => ActionFn(414); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action414::<>(mode, &__start, &__end); + // ("," >)? = ",", Test<"all"> => ActionFn(1059); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0; + let __end = __sym1.2; + let __nt = super::__action1059::<>(mode, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant15(__nt), __end)); - (0, 16) + (2, 18) } pub(crate) fn __reduce58< >( @@ -18969,10 +19025,10 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = => ActionFn(422); + // ("," >)? = => ActionFn(355); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action422::<>(mode, &__start, &__end); + let __nt = super::__action355::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (0, 18) } @@ -18984,14 +19040,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", Test<"all"> => ActionFn(351); + // ("," ) = ",", TestOrStarNamedExpr => ActionFn(547); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action351::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action547::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 19) } pub(crate) fn __reduce60< @@ -19002,15 +19058,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = ",", Test<"all"> => ActionFn(1057); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1057::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (2, 20) + // ("," )* = => ActionFn(545); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action545::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (0, 20) } pub(crate) fn __reduce61< >( @@ -19020,12 +19073,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)? = => ActionFn(350); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action350::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 20) + // ("," )* = ("," )+ => ActionFn(546); + let __sym0 = __pop_Variant16(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action546::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (1, 20) } pub(crate) fn __reduce62< >( @@ -19035,13 +19089,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," ) = ",", TestOrStarNamedExpr => ActionFn(544); + // ("," )+ = ",", TestOrStarNamedExpr => ActionFn(1062); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action544::<>(mode, __sym0, __sym1); + let __nt = super::__action1062::<>(mode, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant16(__nt), __end)); (2, 21) } @@ -19053,12 +19107,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," )* = => ActionFn(542); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action542::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (0, 22) + // ("," )+ = ("," )+, ",", TestOrStarNamedExpr => ActionFn(1063); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant16(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action1063::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (3, 21) } pub(crate) fn __reduce64< >( @@ -19068,13 +19126,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," )* = ("," )+ => ActionFn(543); - let __sym0 = __pop_Variant18(__symbols); + // ("," >) = ",", WithItem<"all"> => ActionFn(298); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant17(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action543::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (1, 22) + let __end = __sym1.2; + let __nt = super::__action298::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (2, 22) } pub(crate) fn __reduce65< >( @@ -19084,15 +19144,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," )+ = ",", TestOrStarNamedExpr => ActionFn(1060); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1060::<>(mode, __sym0, __sym1); + // ("," >)* = => ActionFn(296); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action296::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (2, 23) + (0, 23) } pub(crate) fn __reduce66< >( @@ -19102,16 +19159,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," )+ = ("," )+, ",", TestOrStarNamedExpr => ActionFn(1061); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant0(__symbols); + // ("," >)* = ("," >)+ => ActionFn(297); let __sym0 = __pop_Variant18(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1061::<>(mode, __sym0, __sym1, __sym2); + let __end = __sym0.2; + let __nt = super::__action297::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (3, 23) + (1, 23) } pub(crate) fn __reduce67< >( @@ -19121,14 +19175,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >) = ",", WithItem<"all"> => ActionFn(297); + // ("," >)+ = ",", WithItem<"all"> => ActionFn(1072); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant19(__symbols); + let __sym1 = __pop_Variant17(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action297::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); + let __nt = super::__action1072::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant18(__nt), __end)); (2, 24) } pub(crate) fn __reduce68< @@ -19139,12 +19193,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = => ActionFn(295); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action295::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant20(__nt), __end)); - (0, 25) + // ("," >)+ = ("," >)+, ",", WithItem<"all"> => ActionFn(1073); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant17(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant18(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action1073::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant18(__nt), __end)); + (3, 24) } pub(crate) fn __reduce69< >( @@ -19154,13 +19212,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)* = ("," >)+ => ActionFn(296); - let __sym0 = __pop_Variant20(__symbols); + // ("->" >) = "->", Test<"all"> => ActionFn(285); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action296::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant20(__nt), __end)); - (1, 25) + let __end = __sym1.2; + let __nt = super::__action285::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 25) } pub(crate) fn __reduce70< >( @@ -19170,14 +19230,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ",", WithItem<"all"> => ActionFn(1070); + // ("->" >)? = "->", Test<"all"> => ActionFn(1078); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant19(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1070::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant20(__nt), __end)); + let __nt = super::__action1078::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (2, 26) } pub(crate) fn __reduce71< @@ -19188,16 +19248,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("," >)+ = ("," >)+, ",", WithItem<"all"> => ActionFn(1071); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant19(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant20(__symbols); - let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1071::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant20(__nt), __end)); - (3, 26) + // ("->" >)? = => ActionFn(284); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action284::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (0, 26) } pub(crate) fn __reduce72< >( @@ -19207,14 +19263,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("->" >) = "->", Test<"all"> => ActionFn(284); + // ("." Identifier) = ".", Identifier => ActionFn(361); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action284::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action361::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant19(__nt), __end)); (2, 27) } pub(crate) fn __reduce73< @@ -19225,14 +19281,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("->" >)? = "->", Test<"all"> => ActionFn(1076); + // ("." Identifier)+ = ".", Identifier => ActionFn(1083); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1076::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action1083::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant20(__nt), __end)); (2, 28) } pub(crate) fn __reduce74< @@ -19243,12 +19299,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("->" >)? = => ActionFn(283); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action283::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 28) + // ("." Identifier)+ = ("." Identifier)+, ".", Identifier => ActionFn(1084); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant22(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant20(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action1084::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant20(__nt), __end)); + (3, 28) } pub(crate) fn __reduce75< >( @@ -19258,14 +19318,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("." Identifier) = ".", Identifier => ActionFn(356); + // (":" >) = ":", Test<"all"> => ActionFn(275); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action356::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant21(__nt), __end)); + let __nt = super::__action275::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 29) } pub(crate) fn __reduce76< @@ -19276,14 +19336,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("." Identifier)+ = ".", Identifier => ActionFn(1081); + // (":" >)? = ":", Test<"all"> => ActionFn(1085); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1081::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant22(__nt), __end)); + let __nt = super::__action1085::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (2, 30) } pub(crate) fn __reduce77< @@ -19294,16 +19354,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("." Identifier)+ = ("." Identifier)+, ".", Identifier => ActionFn(1082); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant22(__symbols); - let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1082::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant22(__nt), __end)); - (3, 30) + // (":" >)? = => ActionFn(274); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action274::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (0, 30) } pub(crate) fn __reduce78< >( @@ -19313,14 +19369,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" >) = ":", Test<"all"> => ActionFn(274); + // (":" ) = ":", TestOrStarExpr => ActionFn(272); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action274::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action272::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 31) } pub(crate) fn __reduce79< @@ -19331,14 +19387,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" >)? = ":", Test<"all"> => ActionFn(1083); + // (":" )? = ":", TestOrStarExpr => ActionFn(1092); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1083::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action1092::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (2, 32) } pub(crate) fn __reduce80< @@ -19349,11 +19405,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" >)? = => ActionFn(273); + // (":" )? = => ActionFn(271); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action273::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action271::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (0, 32) } pub(crate) fn __reduce81< @@ -19364,15 +19420,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" ) = ":", TestOrStarExpr => ActionFn(271); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + // ("?") = "?" => ActionFn(351); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action271::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 33) + let __end = __sym0.2; + let __nt = super::__action351::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant0(__nt), __end)); + (1, 33) } pub(crate) fn __reduce82< >( @@ -19382,15 +19436,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" )? = ":", TestOrStarExpr => ActionFn(1090); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + // ("?")+ = "?" => ActionFn(1095); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1090::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (2, 34) + let __end = __sym0.2; + let __nt = super::__action1095::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); + (1, 34) } pub(crate) fn __reduce83< >( @@ -19400,12 +19452,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (":" )? = => ActionFn(270); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action270::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 34) + // ("?")+ = ("?")+, "?" => ActionFn(1096); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant21(__symbols); + let __start = __sym0.0; + let __end = __sym1.2; + let __nt = super::__action1096::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); + (2, 34) } pub(crate) fn __reduce84< >( @@ -19415,11 +19470,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("\n") = "\n" => ActionFn(388); + // ("\n") = "\n" => ActionFn(393); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action388::<>(mode, __sym0); + let __nt = super::__action393::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant0(__nt), __end)); (1, 35) } @@ -19431,11 +19486,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("\n")* = => ActionFn(386); + // ("\n")* = => ActionFn(391); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action386::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant23(__nt), __end)); + let __nt = super::__action391::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); (0, 36) } pub(crate) fn __reduce86< @@ -19446,12 +19501,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("\n")* = ("\n")+ => ActionFn(387); - let __sym0 = __pop_Variant23(__symbols); + // ("\n")* = ("\n")+ => ActionFn(392); + let __sym0 = __pop_Variant21(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action387::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant23(__nt), __end)); + let __nt = super::__action392::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); (1, 36) } pub(crate) fn __reduce87< @@ -19462,12 +19517,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("\n")+ = "\n" => ActionFn(1093); + // ("\n")+ = "\n" => ActionFn(1097); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1093::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant23(__nt), __end)); + let __nt = super::__action1097::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); (1, 37) } pub(crate) fn __reduce88< @@ -19478,14 +19533,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("\n")+ = ("\n")+, "\n" => ActionFn(1094); + // ("\n")+ = ("\n")+, "\n" => ActionFn(1098); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant23(__symbols); + let __sym0 = __pop_Variant21(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1094::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant23(__nt), __end)); + let __nt = super::__action1098::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant21(__nt), __end)); (2, 37) } pub(crate) fn __reduce89< @@ -19496,14 +19551,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("as" ) = "as", Identifier => ActionFn(399); + // ("as" ) = "as", Identifier => ActionFn(404); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action399::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + let __nt = super::__action404::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant22(__nt), __end)); (2, 38) } pub(crate) fn __reduce90< @@ -19514,14 +19569,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("as" )? = "as", Identifier => ActionFn(1097); + // ("as" )? = "as", Identifier => ActionFn(1101); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1097::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant25(__nt), __end)); + let __nt = super::__action1101::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant23(__nt), __end)); (2, 39) } pub(crate) fn __reduce91< @@ -19532,11 +19587,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("as" )? = => ActionFn(398); + // ("as" )? = => ActionFn(403); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action398::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant25(__nt), __end)); + let __nt = super::__action403::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant23(__nt), __end)); (0, 39) } pub(crate) fn __reduce92< @@ -19549,13 +19604,13 @@ mod __parse__Top { { // ("else" ":" ) = "else", ":", Suite => ActionFn(318); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action318::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); (3, 40) } pub(crate) fn __reduce93< @@ -19566,15 +19621,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("else" ":" )? = "else", ":", Suite => ActionFn(1102); + // ("else" ":" )? = "else", ":", Suite => ActionFn(1106); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1102::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant27(__nt), __end)); + let __nt = super::__action1106::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant25(__nt), __end)); (3, 41) } pub(crate) fn __reduce94< @@ -19589,7 +19644,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action317::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant27(__nt), __end)); + __symbols.push((__start, __Symbol::Variant25(__nt), __end)); (0, 41) } pub(crate) fn __reduce95< @@ -19602,13 +19657,13 @@ mod __parse__Top { { // ("finally" ":" ) = "finally", ":", Suite => ActionFn(311); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action311::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); (3, 42) } pub(crate) fn __reduce96< @@ -19619,15 +19674,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("finally" ":" )? = "finally", ":", Suite => ActionFn(1113); + // ("finally" ":" )? = "finally", ":", Suite => ActionFn(1117); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1113::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant27(__nt), __end)); + let __nt = super::__action1117::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant25(__nt), __end)); (3, 43) } pub(crate) fn __reduce97< @@ -19642,7 +19697,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action310::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant27(__nt), __end)); + __symbols.push((__start, __Symbol::Variant25(__nt), __end)); (0, 43) } pub(crate) fn __reduce98< @@ -19653,14 +19708,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("from" >) = "from", Test<"all"> => ActionFn(371); + // ("from" >) = "from", Test<"all"> => ActionFn(376); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action371::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action376::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 44) } pub(crate) fn __reduce99< @@ -19671,14 +19726,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("from" >)? = "from", Test<"all"> => ActionFn(1123); + // ("from" >)? = "from", Test<"all"> => ActionFn(1127); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1123::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action1127::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (2, 45) } pub(crate) fn __reduce100< @@ -19689,11 +19744,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ("from" >)? = => ActionFn(370); + // ("from" >)? = => ActionFn(375); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action370::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action375::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (0, 45) } pub(crate) fn __reduce101< @@ -19704,16 +19759,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (<@L> "elif" ":" ) = "elif", NamedExpressionTest, ":", Suite => ActionFn(701); + // (<@L> "elif" ":" ) = "elif", NamedExpressionTest, ":", Suite => ActionFn(703); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action701::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant28(__nt), __end)); + let __nt = super::__action703::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant26(__nt), __end)); (4, 46) } pub(crate) fn __reduce102< @@ -19728,7 +19783,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action322::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant29(__nt), __end)); + __symbols.push((__start, __Symbol::Variant27(__nt), __end)); (0, 47) } pub(crate) fn __reduce103< @@ -19740,11 +19795,11 @@ mod __parse__Top { ) -> (usize, usize) { // (<@L> "elif" ":" )* = (<@L> "elif" ":" )+ => ActionFn(323); - let __sym0 = __pop_Variant29(__symbols); + let __sym0 = __pop_Variant27(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action323::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant29(__nt), __end)); + __symbols.push((__start, __Symbol::Variant27(__nt), __end)); (1, 47) } pub(crate) fn __reduce104< @@ -19755,16 +19810,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (<@L> "elif" ":" )+ = "elif", NamedExpressionTest, ":", Suite => ActionFn(1126); + // (<@L> "elif" ":" )+ = "elif", NamedExpressionTest, ":", Suite => ActionFn(1130); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1126::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant29(__nt), __end)); + let __nt = super::__action1130::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant27(__nt), __end)); (4, 48) } pub(crate) fn __reduce105< @@ -19775,17 +19830,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (<@L> "elif" ":" )+ = (<@L> "elif" ":" )+, "elif", NamedExpressionTest, ":", Suite => ActionFn(1127); + // (<@L> "elif" ":" )+ = (<@L> "elif" ":" )+, "elif", NamedExpressionTest, ":", Suite => ActionFn(1131); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant29(__symbols); + let __sym0 = __pop_Variant27(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1127::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant29(__nt), __end)); + let __nt = super::__action1131::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant27(__nt), __end)); (5, 48) } pub(crate) fn __reduce106< @@ -19796,15 +19851,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (<@L> "else" ":" ) = "else", ":", Suite => ActionFn(702); + // (<@L> "else" ":" ) = "else", ":", Suite => ActionFn(704); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action702::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + let __nt = super::__action704::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant28(__nt), __end)); (3, 49) } pub(crate) fn __reduce107< @@ -19815,15 +19870,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (<@L> "else" ":" )? = "else", ":", Suite => ActionFn(1130); + // (<@L> "else" ":" )? = "else", ":", Suite => ActionFn(1134); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1130::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant31(__nt), __end)); + let __nt = super::__action1134::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant29(__nt), __end)); (3, 50) } pub(crate) fn __reduce108< @@ -19838,7 +19893,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action320::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant31(__nt), __end)); + __symbols.push((__start, __Symbol::Variant29(__nt), __end)); (0, 50) } pub(crate) fn __reduce109< @@ -19849,14 +19904,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "or") = AndTest<"all">, "or" => ActionFn(433); + // (> "or") = AndTest<"all">, "or" => ActionFn(438); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action433::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action438::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 51) } pub(crate) fn __reduce110< @@ -19867,14 +19922,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "or")+ = AndTest<"all">, "or" => ActionFn(1135); + // (> "or")+ = AndTest<"all">, "or" => ActionFn(1139); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1135::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); + let __nt = super::__action1139::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); (2, 52) } pub(crate) fn __reduce111< @@ -19885,15 +19940,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "or")+ = (> "or")+, AndTest<"all">, "or" => ActionFn(1136); + // (> "or")+ = (> "or")+, AndTest<"all">, "or" => ActionFn(1140); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1136::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); + let __nt = super::__action1140::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); (3, 52) } pub(crate) fn __reduce112< @@ -19904,14 +19959,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",") = FunctionArgument, "," => ActionFn(442); + // ( ",") = FunctionArgument, "," => ActionFn(447); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant32(__symbols); + let __sym0 = __pop_Variant30(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action442::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + let __nt = super::__action447::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); (2, 53) } pub(crate) fn __reduce113< @@ -19922,11 +19977,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")* = => ActionFn(440); + // ( ",")* = => ActionFn(445); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action440::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + let __nt = super::__action445::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant31(__nt), __end)); (0, 54) } pub(crate) fn __reduce114< @@ -19937,12 +19992,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")* = ( ",")+ => ActionFn(441); - let __sym0 = __pop_Variant33(__symbols); + // ( ",")* = ( ",")+ => ActionFn(446); + let __sym0 = __pop_Variant31(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action441::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + let __nt = super::__action446::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant31(__nt), __end)); (1, 54) } pub(crate) fn __reduce115< @@ -19953,14 +20008,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")+ = FunctionArgument, "," => ActionFn(1137); + // ( ",")+ = FunctionArgument, "," => ActionFn(1141); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant32(__symbols); + let __sym0 = __pop_Variant30(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1137::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + let __nt = super::__action1141::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant31(__nt), __end)); (2, 55) } pub(crate) fn __reduce116< @@ -19971,15 +20026,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")+ = ( ",")+, FunctionArgument, "," => ActionFn(1138); + // ( ",")+ = ( ",")+, FunctionArgument, "," => ActionFn(1142); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant32(__symbols); - let __sym0 = __pop_Variant33(__symbols); + let __sym1 = __pop_Variant30(__symbols); + let __sym0 = __pop_Variant31(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1138::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + let __nt = super::__action1142::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant31(__nt), __end)); (3, 55) } pub(crate) fn __reduce117< @@ -19990,14 +20045,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "and") = NotTest<"all">, "and" => ActionFn(447); + // (> "and") = NotTest<"all">, "and" => ActionFn(452); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action447::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action452::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 56) } pub(crate) fn __reduce118< @@ -20008,14 +20063,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "and")+ = NotTest<"all">, "and" => ActionFn(1141); + // (> "and")+ = NotTest<"all">, "and" => ActionFn(1145); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1141::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); + let __nt = super::__action1145::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); (2, 57) } pub(crate) fn __reduce119< @@ -20026,15 +20081,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (> "and")+ = (> "and")+, NotTest<"all">, "and" => ActionFn(1142); + // (> "and")+ = (> "and")+, NotTest<"all">, "and" => ActionFn(1146); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1142::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); + let __nt = super::__action1146::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); (3, 57) } pub(crate) fn __reduce120< @@ -20045,14 +20100,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (>> ",") = OneOrMore>, "," => ActionFn(547); + // (>> ",") = OneOrMore>, "," => ActionFn(550); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action547::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + let __nt = super::__action550::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); (2, 58) } pub(crate) fn __reduce121< @@ -20063,14 +20118,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (>> ",")? = OneOrMore>, "," => ActionFn(1143); + // (>> ",")? = OneOrMore>, "," => ActionFn(1147); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1143::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant35(__nt), __end)); + let __nt = super::__action1147::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant33(__nt), __end)); (2, 59) } pub(crate) fn __reduce122< @@ -20081,11 +20136,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (>> ",")? = => ActionFn(546); + // (>> ",")? = => ActionFn(549); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action546::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant35(__nt), __end)); + let __nt = super::__action549::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant33(__nt), __end)); (0, 59) } pub(crate) fn __reduce123< @@ -20099,11 +20154,11 @@ mod __parse__Top { // ( ",") = Pattern, "," => ActionFn(337); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action337::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); (2, 60) } pub(crate) fn __reduce124< @@ -20114,11 +20169,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")* = => ActionFn(402); + // ( ",")* = => ActionFn(409); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action402::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant37(__nt), __end)); + let __nt = super::__action409::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant35(__nt), __end)); (0, 61) } pub(crate) fn __reduce125< @@ -20129,12 +20184,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")* = ( ",")+ => ActionFn(403); - let __sym0 = __pop_Variant37(__symbols); + // ( ",")* = ( ",")+ => ActionFn(410); + let __sym0 = __pop_Variant35(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action403::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant37(__nt), __end)); + let __nt = super::__action410::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant35(__nt), __end)); (1, 61) } pub(crate) fn __reduce126< @@ -20145,14 +20200,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")+ = Pattern, "," => ActionFn(1160); + // ( ",")+ = Pattern, "," => ActionFn(1164); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1160::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant37(__nt), __end)); + let __nt = super::__action1164::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant35(__nt), __end)); (2, 62) } pub(crate) fn __reduce127< @@ -20163,15 +20218,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")+ = ( ",")+, Pattern, "," => ActionFn(1161); + // ( ",")+ = ( ",")+, Pattern, "," => ActionFn(1165); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant36(__symbols); - let __sym0 = __pop_Variant37(__symbols); + let __sym1 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant35(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1161::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant37(__nt), __end)); + let __nt = super::__action1165::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant35(__nt), __end)); (3, 62) } pub(crate) fn __reduce128< @@ -20182,14 +20237,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ";") = SmallStatement, ";" => ActionFn(385); + // ( ";") = SmallStatement, ";" => ActionFn(390); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action385::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); + let __nt = super::__action390::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); (2, 63) } pub(crate) fn __reduce129< @@ -20200,11 +20255,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ";")* = => ActionFn(383); + // ( ";")* = => ActionFn(388); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action383::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + let __nt = super::__action388::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant37(__nt), __end)); (0, 64) } pub(crate) fn __reduce130< @@ -20215,12 +20270,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ";")* = ( ";")+ => ActionFn(384); - let __sym0 = __pop_Variant39(__symbols); + // ( ";")* = ( ";")+ => ActionFn(389); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action384::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + let __nt = super::__action389::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant37(__nt), __end)); (1, 64) } pub(crate) fn __reduce131< @@ -20231,14 +20286,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ";")+ = SmallStatement, ";" => ActionFn(1164); + // ( ";")+ = SmallStatement, ";" => ActionFn(1168); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1164::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + let __nt = super::__action1168::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant37(__nt), __end)); (2, 65) } pub(crate) fn __reduce132< @@ -20249,15 +20304,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ";")+ = ( ";")+, SmallStatement, ";" => ActionFn(1165); + // ( ";")+ = ( ";")+, SmallStatement, ";" => ActionFn(1169); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant39(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1165::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + let __nt = super::__action1169::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant37(__nt), __end)); (3, 65) } pub(crate) fn __reduce133< @@ -20270,13 +20325,13 @@ mod __parse__Top { { // (> "as" ) = Test<"all">, "as", Identifier => ActionFn(306); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action306::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant40(__nt), __end)); + __symbols.push((__start, __Symbol::Variant38(__nt), __end)); (3, 66) } pub(crate) fn __reduce134< @@ -20287,14 +20342,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",") = OneOrMore>, "," => ActionFn(1481); + // ( ",") = OneOrMore>, "," => ActionFn(1486); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1481::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); + let __nt = super::__action1486::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); (2, 67) } pub(crate) fn __reduce135< @@ -20305,14 +20360,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ( ",")? = OneOrMore>, "," => ActionFn(1484); + // ( ",")? = OneOrMore>, "," => ActionFn(1489); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1484::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant42(__nt), __end)); + let __nt = super::__action1489::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant40(__nt), __end)); (2, 68) } pub(crate) fn __reduce136< @@ -20327,7 +20382,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action302::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant42(__nt), __end)); + __symbols.push((__start, __Symbol::Variant40(__nt), __end)); (0, 68) } pub(crate) fn __reduce137< @@ -20338,12 +20393,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (@L string @R) = string => ActionFn(1184); + // (@L string @R) = string => ActionFn(1188); let __sym0 = __pop_Variant6(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1184::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant43(__nt), __end)); + let __nt = super::__action1188::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant41(__nt), __end)); (1, 69) } pub(crate) fn __reduce138< @@ -20354,12 +20409,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (@L string @R)+ = string => ActionFn(1493); + // (@L string @R)+ = string => ActionFn(1498); let __sym0 = __pop_Variant6(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1493::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant44(__nt), __end)); + let __nt = super::__action1498::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant42(__nt), __end)); (1, 70) } pub(crate) fn __reduce139< @@ -20370,14 +20425,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (@L string @R)+ = (@L string @R)+, string => ActionFn(1494); + // (@L string @R)+ = (@L string @R)+, string => ActionFn(1499); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant6(__symbols); - let __sym0 = __pop_Variant44(__symbols); + let __sym0 = __pop_Variant42(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1494::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant44(__nt), __end)); + let __nt = super::__action1499::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant42(__nt), __end)); (2, 70) } pub(crate) fn __reduce140< @@ -20388,14 +20443,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (CompOp Expression<"all">) = CompOp, Expression<"all"> => ActionFn(490); + // (CompOp Expression<"all">) = CompOp, Expression<"all"> => ActionFn(495); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant56(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant55(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action490::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + let __nt = super::__action495::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant43(__nt), __end)); (2, 71) } pub(crate) fn __reduce141< @@ -20406,14 +20461,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (CompOp Expression<"all">)+ = CompOp, Expression<"all"> => ActionFn(1495); + // (CompOp Expression<"all">)+ = CompOp, Expression<"all"> => ActionFn(1500); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant56(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant55(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1495::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant46(__nt), __end)); + let __nt = super::__action1500::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant44(__nt), __end)); (2, 72) } pub(crate) fn __reduce142< @@ -20424,15 +20479,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (CompOp Expression<"all">)+ = (CompOp Expression<"all">)+, CompOp, Expression<"all"> => ActionFn(1496); + // (CompOp Expression<"all">)+ = (CompOp Expression<"all">)+, CompOp, Expression<"all"> => ActionFn(1501); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant56(__symbols); - let __sym0 = __pop_Variant46(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant55(__symbols); + let __sym0 = __pop_Variant44(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1496::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant46(__nt), __end)); + let __nt = super::__action1501::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant44(__nt), __end)); (3, 72) } pub(crate) fn __reduce143< @@ -20444,11 +20499,11 @@ mod __parse__Top { ) -> (usize, usize) { // (Guard) = Guard => ActionFn(344); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action344::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 73) } pub(crate) fn __reduce144< @@ -20459,12 +20514,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (Guard)? = Guard => ActionFn(1497); - let __sym0 = __pop_Variant16(__symbols); + // (Guard)? = Guard => ActionFn(1502); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1497::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + let __nt = super::__action1502::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (1, 74) } pub(crate) fn __reduce145< @@ -20479,7 +20534,7 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action343::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); (0, 74) } pub(crate) fn __reduce146< @@ -20490,12 +20545,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (ParameterList) = ParameterList => ActionFn(277); - let __sym0 = __pop_Variant47(__symbols); + // (ParameterList) = ParameterList => ActionFn(278); + let __sym0 = __pop_Variant45(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action277::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); + let __nt = super::__action278::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); (1, 75) } pub(crate) fn __reduce147< @@ -20506,12 +20561,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (ParameterList)? = ParameterList => ActionFn(1500); - let __sym0 = __pop_Variant47(__symbols); + // (ParameterList)? = ParameterList => ActionFn(1505); + let __sym0 = __pop_Variant45(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1500::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + let __nt = super::__action1505::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant46(__nt), __end)); (1, 76) } pub(crate) fn __reduce148< @@ -20522,11 +20577,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // (ParameterList)? = => ActionFn(276); + // (ParameterList)? = => ActionFn(277); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action276::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + let __nt = super::__action277::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant46(__nt), __end)); (0, 76) } pub(crate) fn __reduce149< @@ -20537,11 +20592,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // @L = => ActionFn(390); + // @L = => ActionFn(395); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action390::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + let __nt = super::__action395::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant47(__nt), __end)); (0, 77) } pub(crate) fn __reduce150< @@ -20552,11 +20607,11 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // @R = => ActionFn(389); + // @R = => ActionFn(394); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action389::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant49(__nt), __end)); + let __nt = super::__action394::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant47(__nt), __end)); (0, 78) } pub(crate) fn __reduce151< @@ -20567,12 +20622,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AddOp = "+" => ActionFn(194); + // AddOp = "+" => ActionFn(198); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action194::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); + let __nt = super::__action198::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); (1, 79) } pub(crate) fn __reduce152< @@ -20583,12 +20638,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AddOp = "-" => ActionFn(195); + // AddOp = "-" => ActionFn(199); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action195::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); + let __nt = super::__action199::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); (1, 79) } pub(crate) fn __reduce153< @@ -20599,15 +20654,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AddOpExpr = ConstantExpr, AddOp, ConstantAtom => ActionFn(1185); + // AddOpExpr = ConstantExpr, AddOp, ConstantAtom => ActionFn(1189); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1185::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1189::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (3, 80) } pub(crate) fn __reduce154< @@ -20618,15 +20673,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndExpression<"all"> = AndExpression<"all">, "&", ShiftExpression<"all"> => ActionFn(1186); + // AndExpression<"all"> = AndExpression<"all">, "&", ShiftExpression<"all"> => ActionFn(1190); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1186::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1190::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (3, 81) } pub(crate) fn __reduce155< @@ -20637,12 +20692,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndExpression<"all"> = ShiftExpression<"all"> => ActionFn(451); - let __sym0 = __pop_Variant16(__symbols); + // AndExpression<"all"> = ShiftExpression<"all"> => ActionFn(482); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action451::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action482::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 81) } pub(crate) fn __reduce156< @@ -20653,15 +20708,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndExpression<"no-withitems"> = AndExpression<"all">, "&", ShiftExpression<"all"> => ActionFn(1187); + // AndExpression<"no-withitems"> = AndExpression<"all">, "&", ShiftExpression<"all"> => ActionFn(1191); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1187::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1191::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (3, 82) } pub(crate) fn __reduce157< @@ -20672,12 +20727,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndExpression<"no-withitems"> = ShiftExpression<"no-withitems"> => ActionFn(510); - let __sym0 = __pop_Variant16(__symbols); + // AndExpression<"no-withitems"> = ShiftExpression<"no-withitems"> => ActionFn(513); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action510::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action513::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 82) } pub(crate) fn __reduce158< @@ -20688,14 +20743,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndTest<"all"> = (> "and")+, NotTest<"all"> => ActionFn(1188); + // AndTest<"all"> = (> "and")+, NotTest<"all"> => ActionFn(1192); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1188::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1192::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 83) } pub(crate) fn __reduce159< @@ -20706,12 +20761,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndTest<"all"> = NotTest<"all"> => ActionFn(435); - let __sym0 = __pop_Variant16(__symbols); + // AndTest<"all"> = NotTest<"all"> => ActionFn(440); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action435::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action440::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 83) } pub(crate) fn __reduce160< @@ -20722,14 +20777,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndTest<"no-withitems"> = (> "and")+, NotTest<"all"> => ActionFn(1189); + // AndTest<"no-withitems"> = (> "and")+, NotTest<"all"> => ActionFn(1193); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1189::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1193::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 84) } pub(crate) fn __reduce161< @@ -20740,12 +20795,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AndTest<"no-withitems"> = NotTest<"no-withitems"> => ActionFn(479); - let __sym0 = __pop_Variant16(__symbols); + // AndTest<"no-withitems"> = NotTest<"no-withitems"> => ActionFn(486); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action479::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action486::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 84) } pub(crate) fn __reduce166< @@ -20756,16 +20811,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ArithmeticExpression<"all"> = ArithmeticExpression<"all">, AddOp, Term<"all"> => ActionFn(1190); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // Arguments? = Arguments => ActionFn(268); + let __sym0 = __pop_Variant49(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1190::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 86) + let __end = __sym0.2; + let __nt = super::__action268::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant50(__nt), __end)); + (1, 86) } pub(crate) fn __reduce167< >( @@ -20775,13 +20827,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ArithmeticExpression<"all"> = Term<"all"> => ActionFn(492); - let __sym0 = __pop_Variant16(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action492::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 86) + // Arguments? = => ActionFn(269); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action269::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant50(__nt), __end)); + (0, 86) } pub(crate) fn __reduce168< >( @@ -20791,15 +20842,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ArithmeticExpression<"no-withitems"> = ArithmeticExpression<"all">, AddOp, Term<"all"> => ActionFn(1191); + // ArithmeticExpression<"all"> = ArithmeticExpression<"all">, AddOp, Term<"all"> => ActionFn(1195); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1191::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1195::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (3, 87) } pub(crate) fn __reduce169< @@ -20810,14 +20861,33 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ArithmeticExpression<"no-withitems"> = Term<"no-withitems"> => ActionFn(537); - let __sym0 = __pop_Variant16(__symbols); + // ArithmeticExpression<"all"> = Term<"all"> => ActionFn(499); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action537::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action499::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 87) } + pub(crate) fn __reduce170< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // ArithmeticExpression<"no-withitems"> = ArithmeticExpression<"all">, AddOp, Term<"all"> => ActionFn(1196); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); + let __start = __sym0.0; + let __end = __sym2.2; + let __nt = super::__action1196::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 88) + } pub(crate) fn __reduce171< >( mode: Mode, @@ -20826,19 +20896,35 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssertStatement = "assert", Test<"all">, ",", Test<"all"> => ActionFn(1193); + // ArithmeticExpression<"no-withitems"> = Term<"no-withitems"> => ActionFn(523); + let __sym0 = __pop_Variant14(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action523::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 88) + } + pub(crate) fn __reduce173< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // AssertStatement = "assert", Test<"all">, ",", Test<"all"> => ActionFn(1198); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1193::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 89) + let __nt = super::__action1198::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 90) } - pub(crate) fn __reduce172< + pub(crate) fn __reduce174< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20846,17 +20932,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssertStatement = "assert", Test<"all"> => ActionFn(1194); + // AssertStatement = "assert", Test<"all"> => ActionFn(1199); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1194::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 89) + let __nt = super::__action1199::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 90) } - pub(crate) fn __reduce173< + pub(crate) fn __reduce175< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20864,17 +20950,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix = "=", TestListOrYieldExpr => ActionFn(28); + // AssignSuffix = "=", TestListOrYieldExpr => ActionFn(29); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action28::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 90) + let __nt = super::__action29::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 91) } - pub(crate) fn __reduce174< + pub(crate) fn __reduce176< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20882,17 +20968,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix = "=", LineMagicExpr => ActionFn(29); + // AssignSuffix = "=", IpyEscapeCommandExpr => ActionFn(30); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action29::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 90) + let __nt = super::__action30::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 91) } - pub(crate) fn __reduce175< + pub(crate) fn __reduce177< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20900,14 +20986,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix* = => ActionFn(379); + // AssignSuffix* = => ActionFn(384); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action379::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (0, 91) + let __nt = super::__action384::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (0, 92) } - pub(crate) fn __reduce176< + pub(crate) fn __reduce178< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20915,15 +21001,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix* = AssignSuffix+ => ActionFn(380); - let __sym0 = __pop_Variant18(__symbols); + // AssignSuffix* = AssignSuffix+ => ActionFn(385); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action380::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (1, 91) + let __nt = super::__action385::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (1, 92) } - pub(crate) fn __reduce177< + pub(crate) fn __reduce179< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20931,15 +21017,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix+ = AssignSuffix => ActionFn(395); - let __sym0 = __pop_Variant16(__symbols); + // AssignSuffix+ = AssignSuffix => ActionFn(400); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action395::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (1, 92) + let __nt = super::__action400::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (1, 93) } - pub(crate) fn __reduce178< + pub(crate) fn __reduce180< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20947,17 +21033,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix+ = AssignSuffix+, AssignSuffix => ActionFn(396); + // AssignSuffix+ = AssignSuffix+, AssignSuffix => ActionFn(401); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action396::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (2, 92) + let __nt = super::__action401::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (2, 93) } - pub(crate) fn __reduce179< + pub(crate) fn __reduce181< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20965,15 +21051,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix? = AssignSuffix => ActionFn(374); - let __sym0 = __pop_Variant16(__symbols); + // AssignSuffix? = AssignSuffix => ActionFn(379); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action374::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (1, 93) + let __nt = super::__action379::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (1, 94) } - pub(crate) fn __reduce180< + pub(crate) fn __reduce182< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20981,14 +21067,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AssignSuffix? = => ActionFn(375); + // AssignSuffix? = => ActionFn(380); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action375::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 93) + let __nt = super::__action380::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (0, 94) } - pub(crate) fn __reduce182< + pub(crate) fn __reduce184< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -20996,15 +21082,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = Constant => ActionFn(1195); - let __sym0 = __pop_Variant57(__symbols); + // Atom<"all"> = Constant => ActionFn(1200); + let __sym0 = __pop_Variant56(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1195::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1200::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce183< + pub(crate) fn __reduce185< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21012,15 +21098,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = Identifier => ActionFn(1196); - let __sym0 = __pop_Variant24(__symbols); + // Atom<"all"> = Identifier => ActionFn(1201); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1196::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1201::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce184< + pub(crate) fn __reduce186< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21028,18 +21114,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "[", ListLiteralValues, "]" => ActionFn(1557); + // Atom<"all"> = "[", ListLiteralValues, "]" => ActionFn(1564); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1557::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + let __nt = super::__action1564::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - pub(crate) fn __reduce185< + pub(crate) fn __reduce187< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21047,17 +21133,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "[", "]" => ActionFn(1558); + // Atom<"all"> = "[", "]" => ActionFn(1565); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1558::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 94) + let __nt = super::__action1565::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 95) } - pub(crate) fn __reduce186< + pub(crate) fn __reduce188< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21065,19 +21151,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "[", TestOrStarNamedExpr, CompFor, "]" => ActionFn(1198); + // Atom<"all"> = "[", TestOrStarNamedExpr, CompFor, "]" => ActionFn(1203); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1198::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + let __nt = super::__action1203::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - pub(crate) fn __reduce187< + pub(crate) fn __reduce189< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21085,19 +21171,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "(", OneOrMore>, ",", ")" => ActionFn(1199); + // Atom<"all"> = "(", OneOrMore>, ",", ")" => ActionFn(1204); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1199::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + let __nt = super::__action1204::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - pub(crate) fn __reduce188< + pub(crate) fn __reduce190< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21105,18 +21191,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "(", OneOrMore>, ")" => ActionFn(1200); + // Atom<"all"> = "(", OneOrMore>, ")" => ActionFn(1205); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1200::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + let __nt = super::__action1205::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - pub(crate) fn __reduce197< + pub(crate) fn __reduce199< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21124,17 +21210,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "(", ")" => ActionFn(1209); + // Atom<"all"> = "(", ")" => ActionFn(1214); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1209::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 94) + let __nt = super::__action1214::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 95) } - pub(crate) fn __reduce198< + pub(crate) fn __reduce200< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21142,18 +21228,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "(", YieldExpr, ")" => ActionFn(525); + // Atom<"all"> = "(", YieldExpr, ")" => ActionFn(532); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action525::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + let __nt = super::__action532::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - pub(crate) fn __reduce199< + pub(crate) fn __reduce201< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21161,19 +21247,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "(", NamedExpressionTest, CompFor, ")" => ActionFn(1210); + // Atom<"all"> = "(", NamedExpressionTest, CompFor, ")" => ActionFn(1215); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1210::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + let __nt = super::__action1215::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - pub(crate) fn __reduce201< + pub(crate) fn __reduce203< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21181,18 +21267,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "{", DictLiteralValues, "}" => ActionFn(1541); + // Atom<"all"> = "{", DictLiteralValues, "}" => ActionFn(1548); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant62(__symbols); + let __sym1 = __pop_Variant61(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1541::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + let __nt = super::__action1548::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - pub(crate) fn __reduce202< + pub(crate) fn __reduce204< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21200,17 +21286,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "{", "}" => ActionFn(1542); + // Atom<"all"> = "{", "}" => ActionFn(1549); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1542::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 94) + let __nt = super::__action1549::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 95) } - pub(crate) fn __reduce203< + pub(crate) fn __reduce205< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21218,19 +21304,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "{", DictEntry, CompFor, "}" => ActionFn(1213); + // Atom<"all"> = "{", DictEntry, CompFor, "}" => ActionFn(1218); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant61(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant60(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1213::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + let __nt = super::__action1218::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - pub(crate) fn __reduce204< + pub(crate) fn __reduce206< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21238,18 +21324,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "{", SetLiteralValues, "}" => ActionFn(1214); + // Atom<"all"> = "{", SetLiteralValues, "}" => ActionFn(1219); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1214::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 94) + let __nt = super::__action1219::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 95) } - pub(crate) fn __reduce205< + pub(crate) fn __reduce207< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21257,19 +21343,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "{", NamedExpressionTest, CompFor, "}" => ActionFn(1215); + // Atom<"all"> = "{", NamedExpressionTest, CompFor, "}" => ActionFn(1220); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1215::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 94) + let __nt = super::__action1220::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 95) } - pub(crate) fn __reduce206< + pub(crate) fn __reduce208< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21277,15 +21363,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "True" => ActionFn(1216); + // Atom<"all"> = "True" => ActionFn(1221); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1216::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1221::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce207< + pub(crate) fn __reduce209< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21293,15 +21379,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "False" => ActionFn(1217); + // Atom<"all"> = "False" => ActionFn(1222); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1217::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1222::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce208< + pub(crate) fn __reduce210< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21309,15 +21395,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "None" => ActionFn(1218); + // Atom<"all"> = "None" => ActionFn(1223); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1218::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1223::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce209< + pub(crate) fn __reduce211< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21325,15 +21411,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"all"> = "..." => ActionFn(1219); + // Atom<"all"> = "..." => ActionFn(1224); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1219::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 94) + let __nt = super::__action1224::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 95) } - pub(crate) fn __reduce211< + pub(crate) fn __reduce213< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21341,15 +21427,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = Constant => ActionFn(1220); - let __sym0 = __pop_Variant57(__symbols); + // Atom<"no-withitems"> = Constant => ActionFn(1225); + let __sym0 = __pop_Variant56(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1220::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1225::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce212< + pub(crate) fn __reduce214< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21357,15 +21443,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = Identifier => ActionFn(1221); - let __sym0 = __pop_Variant24(__symbols); + // Atom<"no-withitems"> = Identifier => ActionFn(1226); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1221::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1226::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce213< + pub(crate) fn __reduce215< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21373,18 +21459,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "[", ListLiteralValues, "]" => ActionFn(1559); + // Atom<"no-withitems"> = "[", ListLiteralValues, "]" => ActionFn(1566); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1559::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 95) + let __nt = super::__action1566::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 96) } - pub(crate) fn __reduce214< + pub(crate) fn __reduce216< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21392,17 +21478,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "[", "]" => ActionFn(1560); + // Atom<"no-withitems"> = "[", "]" => ActionFn(1567); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1560::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 95) + let __nt = super::__action1567::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 96) } - pub(crate) fn __reduce215< + pub(crate) fn __reduce217< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21410,19 +21496,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "[", TestOrStarNamedExpr, CompFor, "]" => ActionFn(1223); + // Atom<"no-withitems"> = "[", TestOrStarNamedExpr, CompFor, "]" => ActionFn(1228); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1223::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) + let __nt = super::__action1228::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } - pub(crate) fn __reduce224< + pub(crate) fn __reduce226< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21430,17 +21516,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "(", ")" => ActionFn(1232); + // Atom<"no-withitems"> = "(", ")" => ActionFn(1237); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1232::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 95) + let __nt = super::__action1237::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 96) } - pub(crate) fn __reduce225< + pub(crate) fn __reduce227< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21448,18 +21534,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "(", YieldExpr, ")" => ActionFn(569); + // Atom<"no-withitems"> = "(", YieldExpr, ")" => ActionFn(574); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action569::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 95) + let __nt = super::__action574::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 96) } - pub(crate) fn __reduce226< + pub(crate) fn __reduce228< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21467,19 +21553,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "(", NamedExpressionTest, CompFor, ")" => ActionFn(1233); + // Atom<"no-withitems"> = "(", NamedExpressionTest, CompFor, ")" => ActionFn(1238); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1233::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) + let __nt = super::__action1238::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } - pub(crate) fn __reduce228< + pub(crate) fn __reduce230< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21487,18 +21573,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "{", DictLiteralValues, "}" => ActionFn(1543); + // Atom<"no-withitems"> = "{", DictLiteralValues, "}" => ActionFn(1550); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant62(__symbols); + let __sym1 = __pop_Variant61(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1543::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 95) + let __nt = super::__action1550::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 96) } - pub(crate) fn __reduce229< + pub(crate) fn __reduce231< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21506,17 +21592,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "{", "}" => ActionFn(1544); + // Atom<"no-withitems"> = "{", "}" => ActionFn(1551); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1544::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 95) + let __nt = super::__action1551::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 96) } - pub(crate) fn __reduce230< + pub(crate) fn __reduce232< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21524,19 +21610,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "{", DictEntry, CompFor, "}" => ActionFn(1236); + // Atom<"no-withitems"> = "{", DictEntry, CompFor, "}" => ActionFn(1241); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant61(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant60(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1236::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) + let __nt = super::__action1241::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } - pub(crate) fn __reduce231< + pub(crate) fn __reduce233< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21544,18 +21630,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "{", SetLiteralValues, "}" => ActionFn(1237); + // Atom<"no-withitems"> = "{", SetLiteralValues, "}" => ActionFn(1242); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1237::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 95) + let __nt = super::__action1242::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 96) } - pub(crate) fn __reduce232< + pub(crate) fn __reduce234< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21563,19 +21649,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "{", NamedExpressionTest, CompFor, "}" => ActionFn(1238); + // Atom<"no-withitems"> = "{", NamedExpressionTest, CompFor, "}" => ActionFn(1243); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant54(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant53(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1238::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 95) + let __nt = super::__action1243::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 96) } - pub(crate) fn __reduce233< + pub(crate) fn __reduce235< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21583,15 +21669,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "True" => ActionFn(1239); + // Atom<"no-withitems"> = "True" => ActionFn(1244); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1239::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1244::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce234< + pub(crate) fn __reduce236< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21599,15 +21685,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "False" => ActionFn(1240); + // Atom<"no-withitems"> = "False" => ActionFn(1245); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1240::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1245::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce235< + pub(crate) fn __reduce237< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21615,15 +21701,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "None" => ActionFn(1241); + // Atom<"no-withitems"> = "None" => ActionFn(1246); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1241::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1246::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce236< + pub(crate) fn __reduce238< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21631,15 +21717,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Atom<"no-withitems"> = "..." => ActionFn(1242); + // Atom<"no-withitems"> = "..." => ActionFn(1247); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1242::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 95) + let __nt = super::__action1247::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 96) } - pub(crate) fn __reduce237< + pub(crate) fn __reduce239< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21647,15 +21733,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"all"> = Atom<"all"> => ActionFn(513); - let __sym0 = __pop_Variant16(__symbols); + // AtomExpr2<"all"> = Atom<"all"> => ActionFn(516); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action513::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 96) + let __nt = super::__action516::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 97) } - pub(crate) fn __reduce238< + pub(crate) fn __reduce240< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21663,19 +21749,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"all"> = AtomExpr2<"all">, "(", ArgumentList, ")" => ActionFn(1243); - assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant51(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // AtomExpr2<"all"> = AtomExpr2<"all">, Arguments => ActionFn(1248); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant49(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; - let __end = __sym3.2; - let __nt = super::__action1243::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 96) + let __end = __sym1.2; + let __nt = super::__action1248::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 97) } - pub(crate) fn __reduce239< + pub(crate) fn __reduce241< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21683,19 +21767,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"all"> = AtomExpr2<"all">, "[", SubscriptList, "]" => ActionFn(1244); + // AtomExpr2<"all"> = AtomExpr2<"all">, "[", SubscriptList, "]" => ActionFn(1249); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1244::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 96) + let __nt = super::__action1249::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 97) } - pub(crate) fn __reduce240< + pub(crate) fn __reduce242< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21703,18 +21787,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"all"> = AtomExpr2<"all">, ".", Identifier => ActionFn(1245); + // AtomExpr2<"all"> = AtomExpr2<"all">, ".", Identifier => ActionFn(1250); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1245::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 96) + let __nt = super::__action1250::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 97) } - pub(crate) fn __reduce241< + pub(crate) fn __reduce243< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21722,15 +21806,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"no-withitems"> = Atom<"no-withitems"> => ActionFn(558); - let __sym0 = __pop_Variant16(__symbols); + // AtomExpr2<"no-withitems"> = Atom<"no-withitems"> => ActionFn(563); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action558::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 97) + let __nt = super::__action563::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 98) } - pub(crate) fn __reduce242< + pub(crate) fn __reduce244< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21738,19 +21822,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, "(", ArgumentList, ")" => ActionFn(1246); - assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant51(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, Arguments => ActionFn(1251); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant49(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; - let __end = __sym3.2; - let __nt = super::__action1246::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 97) + let __end = __sym1.2; + let __nt = super::__action1251::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 98) } - pub(crate) fn __reduce243< + pub(crate) fn __reduce245< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21758,19 +21840,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, "[", SubscriptList, "]" => ActionFn(1247); + // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, "[", SubscriptList, "]" => ActionFn(1252); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1247::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 97) + let __nt = super::__action1252::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 98) } - pub(crate) fn __reduce244< + pub(crate) fn __reduce246< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21778,18 +21860,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, ".", Identifier => ActionFn(1248); + // AtomExpr2<"no-withitems"> = AtomExpr2<"all">, ".", Identifier => ActionFn(1253); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1248::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 97) + let __nt = super::__action1253::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 98) } - pub(crate) fn __reduce245< + pub(crate) fn __reduce247< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21797,17 +21879,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr<"all"> = "await", AtomExpr2<"all"> => ActionFn(1249); + // AtomExpr<"all"> = "await", AtomExpr2<"all"> => ActionFn(1254); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1249::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 98) + let __nt = super::__action1254::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 99) } - pub(crate) fn __reduce246< + pub(crate) fn __reduce248< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21815,15 +21897,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr<"all"> = AtomExpr2<"all"> => ActionFn(508); - let __sym0 = __pop_Variant16(__symbols); + // AtomExpr<"all"> = AtomExpr2<"all"> => ActionFn(515); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action508::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 98) + let __nt = super::__action515::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 99) } - pub(crate) fn __reduce247< + pub(crate) fn __reduce249< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21831,33 +21913,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AtomExpr<"no-withitems"> = "await", AtomExpr2<"all"> => ActionFn(1250); + // AtomExpr<"no-withitems"> = "await", AtomExpr2<"all"> => ActionFn(1255); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1250::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 99) - } - pub(crate) fn __reduce248< - >( - mode: Mode, - __lookahead_start: Option<&TextSize>, - __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, - _: core::marker::PhantomData<()>, - ) -> (usize, usize) - { - // AtomExpr<"no-withitems"> = AtomExpr2<"no-withitems"> => ActionFn(557); - let __sym0 = __pop_Variant16(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action557::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 99) + let __nt = super::__action1255::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 100) } - pub(crate) fn __reduce249< + pub(crate) fn __reduce250< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21865,15 +21931,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "+=" => ActionFn(39); - let __sym0 = __pop_Variant0(__symbols); + // AtomExpr<"no-withitems"> = AtomExpr2<"no-withitems"> => ActionFn(562); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action39::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); + let __nt = super::__action562::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 100) } - pub(crate) fn __reduce250< + pub(crate) fn __reduce251< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21881,15 +21947,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "-=" => ActionFn(40); + // AugAssign = "+=" => ActionFn(40); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action40::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce251< + pub(crate) fn __reduce252< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21897,15 +21963,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "*=" => ActionFn(41); + // AugAssign = "-=" => ActionFn(41); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action41::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce252< + pub(crate) fn __reduce253< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21913,15 +21979,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "@=" => ActionFn(42); + // AugAssign = "*=" => ActionFn(42); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action42::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce253< + pub(crate) fn __reduce254< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21929,15 +21995,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "/=" => ActionFn(43); + // AugAssign = "@=" => ActionFn(43); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action43::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce254< + pub(crate) fn __reduce255< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21945,15 +22011,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "%=" => ActionFn(44); + // AugAssign = "/=" => ActionFn(44); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action44::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce255< + pub(crate) fn __reduce256< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21961,15 +22027,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "&=" => ActionFn(45); + // AugAssign = "%=" => ActionFn(45); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action45::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce256< + pub(crate) fn __reduce257< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21977,15 +22043,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "|=" => ActionFn(46); + // AugAssign = "&=" => ActionFn(46); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action46::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce257< + pub(crate) fn __reduce258< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -21993,15 +22059,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "^=" => ActionFn(47); + // AugAssign = "|=" => ActionFn(47); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action47::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce258< + pub(crate) fn __reduce259< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22009,15 +22075,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "<<=" => ActionFn(48); + // AugAssign = "^=" => ActionFn(48); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action48::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce259< + pub(crate) fn __reduce260< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22025,15 +22091,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = ">>=" => ActionFn(49); + // AugAssign = "<<=" => ActionFn(49); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action49::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce260< + pub(crate) fn __reduce261< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22041,15 +22107,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "**=" => ActionFn(50); + // AugAssign = ">>=" => ActionFn(50); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action50::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce261< + pub(crate) fn __reduce262< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22057,15 +22123,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // AugAssign = "//=" => ActionFn(51); + // AugAssign = "**=" => ActionFn(51); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action51::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 100) + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 101) } - pub(crate) fn __reduce262< + pub(crate) fn __reduce263< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22073,15 +22139,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CapturePattern = Identifier => ActionFn(1251); - let __sym0 = __pop_Variant24(__symbols); + // AugAssign = "//=" => ActionFn(52); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1251::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + let __nt = super::__action52::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); (1, 101) } - pub(crate) fn __reduce263< + pub(crate) fn __reduce264< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22089,23 +22155,37 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = "class", Identifier, TypeParamList, "(", ArgumentList, ")", ":", Suite => ActionFn(1713); - assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); - let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant51(__symbols); - let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant82(__symbols); - let __sym1 = __pop_Variant24(__symbols); + // CapturePattern = Identifier => ActionFn(1256); + let __sym0 = __pop_Variant22(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action1256::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 102) + } + pub(crate) fn __reduce265< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // ClassDef = "class", Identifier, TypeParams, Arguments, ":", Suite => ActionFn(1720); + assert!(__symbols.len() >= 6); + let __sym5 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant0(__symbols); + let __sym3 = __pop_Variant49(__symbols); + let __sym2 = __pop_Variant91(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym7.2; - let __nt = super::__action1713::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 102) + let __end = __sym5.2; + let __nt = super::__action1720::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 103) } - pub(crate) fn __reduce264< + pub(crate) fn __reduce266< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22113,22 +22193,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = "class", Identifier, "(", ArgumentList, ")", ":", Suite => ActionFn(1714); - assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); - let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant51(__symbols); - let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant24(__symbols); + // ClassDef = "class", Identifier, Arguments, ":", Suite => ActionFn(1721); + assert!(__symbols.len() >= 5); + let __sym4 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant0(__symbols); + let __sym2 = __pop_Variant49(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym6.2; - let __nt = super::__action1714::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 102) + let __end = __sym4.2; + let __nt = super::__action1721::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 103) } - pub(crate) fn __reduce265< + pub(crate) fn __reduce267< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22136,24 +22214,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = Decorator+, "class", Identifier, TypeParamList, "(", ArgumentList, ")", ":", Suite => ActionFn(1715); - assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant26(__symbols); - let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant51(__symbols); - let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + // ClassDef = Decorator+, "class", Identifier, TypeParams, Arguments, ":", Suite => ActionFn(1722); + assert!(__symbols.len() >= 7); + let __sym6 = __pop_Variant24(__symbols); + let __sym5 = __pop_Variant0(__symbols); + let __sym4 = __pop_Variant49(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; - let __end = __sym8.2; - let __nt = super::__action1715::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (9, 102) + let __end = __sym6.2; + let __nt = super::__action1722::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 103) } - pub(crate) fn __reduce266< + pub(crate) fn __reduce268< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22161,23 +22237,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = Decorator+, "class", Identifier, "(", ArgumentList, ")", ":", Suite => ActionFn(1716); - assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); - let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant51(__symbols); - let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + // ClassDef = Decorator+, "class", Identifier, Arguments, ":", Suite => ActionFn(1723); + assert!(__symbols.len() >= 6); + let __sym5 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant0(__symbols); + let __sym3 = __pop_Variant49(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; - let __end = __sym7.2; - let __nt = super::__action1716::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 102) + let __end = __sym5.2; + let __nt = super::__action1723::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 103) } - pub(crate) fn __reduce267< + pub(crate) fn __reduce269< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22185,20 +22259,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = "class", Identifier, TypeParamList, ":", Suite => ActionFn(1717); + // ClassDef = "class", Identifier, TypeParams, ":", Suite => ActionFn(1724); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant82(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant91(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1717::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 102) + let __nt = super::__action1724::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 103) } - pub(crate) fn __reduce268< + pub(crate) fn __reduce270< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22206,19 +22280,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = "class", Identifier, ":", Suite => ActionFn(1718); + // ClassDef = "class", Identifier, ":", Suite => ActionFn(1725); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1718::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 102) + let __nt = super::__action1725::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 103) } - pub(crate) fn __reduce269< + pub(crate) fn __reduce271< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22226,21 +22300,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = Decorator+, "class", Identifier, TypeParamList, ":", Suite => ActionFn(1719); + // ClassDef = Decorator+, "class", Identifier, TypeParams, ":", Suite => ActionFn(1726); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1719::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 102) + let __nt = super::__action1726::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 103) } - pub(crate) fn __reduce270< + pub(crate) fn __reduce272< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22248,20 +22322,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassDef = Decorator+, "class", Identifier, ":", Suite => ActionFn(1720); + // ClassDef = Decorator+, "class", Identifier, ":", Suite => ActionFn(1727); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1720::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 102) + let __nt = super::__action1727::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 103) } - pub(crate) fn __reduce271< + pub(crate) fn __reduce273< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22269,22 +22343,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ",", OneOrMore, ",", ")" => ActionFn(1252); + // ClassPattern = MatchName, "(", OneOrMore, ",", OneOrMore, ",", ")" => ActionFn(1257); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant79(__symbols); + let __sym4 = __pop_Variant78(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1252::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (7, 103) + let __nt = super::__action1257::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (7, 104) } - pub(crate) fn __reduce272< + pub(crate) fn __reduce274< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22292,21 +22366,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ",", OneOrMore, ")" => ActionFn(1253); + // ClassPattern = MatchName, "(", OneOrMore, ",", OneOrMore, ")" => ActionFn(1258); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant79(__symbols); + let __sym4 = __pop_Variant78(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1253::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (6, 103) + let __nt = super::__action1258::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (6, 104) } - pub(crate) fn __reduce273< + pub(crate) fn __reduce275< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22314,20 +22388,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ",", ")" => ActionFn(1254); + // ClassPattern = MatchName, "(", OneOrMore, ",", ")" => ActionFn(1259); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1254::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 103) + let __nt = super::__action1259::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 104) } - pub(crate) fn __reduce274< + pub(crate) fn __reduce276< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22335,19 +22409,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ")" => ActionFn(1255); + // ClassPattern = MatchName, "(", OneOrMore, ")" => ActionFn(1260); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1255::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 103) + let __nt = super::__action1260::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 104) } - pub(crate) fn __reduce275< + pub(crate) fn __reduce277< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22355,20 +22429,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ",", ")" => ActionFn(1256); + // ClassPattern = MatchName, "(", OneOrMore, ",", ")" => ActionFn(1261); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant79(__symbols); + let __sym2 = __pop_Variant78(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1256::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 103) + let __nt = super::__action1261::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 104) } - pub(crate) fn __reduce276< + pub(crate) fn __reduce278< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22376,19 +22450,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", OneOrMore, ")" => ActionFn(1257); + // ClassPattern = MatchName, "(", OneOrMore, ")" => ActionFn(1262); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant79(__symbols); + let __sym2 = __pop_Variant78(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1257::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 103) + let __nt = super::__action1262::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 104) } - pub(crate) fn __reduce277< + pub(crate) fn __reduce279< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22396,18 +22470,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchName, "(", ")" => ActionFn(1258); + // ClassPattern = MatchName, "(", ")" => ActionFn(1263); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1258::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 103) + let __nt = super::__action1263::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 104) } - pub(crate) fn __reduce278< + pub(crate) fn __reduce280< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22415,22 +22489,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", OneOrMore, ",", ")" => ActionFn(1259); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", OneOrMore, ",", ")" => ActionFn(1264); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant79(__symbols); + let __sym4 = __pop_Variant78(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1259::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (7, 103) + let __nt = super::__action1264::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (7, 104) } - pub(crate) fn __reduce279< + pub(crate) fn __reduce281< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22438,21 +22512,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", OneOrMore, ")" => ActionFn(1260); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", OneOrMore, ")" => ActionFn(1265); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant79(__symbols); + let __sym4 = __pop_Variant78(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1260::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (6, 103) + let __nt = super::__action1265::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (6, 104) } - pub(crate) fn __reduce280< + pub(crate) fn __reduce282< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22460,20 +22534,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", ")" => ActionFn(1261); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", ")" => ActionFn(1266); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1261::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 103) + let __nt = super::__action1266::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 104) } - pub(crate) fn __reduce281< + pub(crate) fn __reduce283< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22481,19 +22555,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ")" => ActionFn(1262); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ")" => ActionFn(1267); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant53(__symbols); + let __sym2 = __pop_Variant52(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1262::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 103) + let __nt = super::__action1267::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 104) } - pub(crate) fn __reduce282< + pub(crate) fn __reduce284< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22501,20 +22575,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", ")" => ActionFn(1263); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ",", ")" => ActionFn(1268); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant79(__symbols); + let __sym2 = __pop_Variant78(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1263::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 103) + let __nt = super::__action1268::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 104) } - pub(crate) fn __reduce283< + pub(crate) fn __reduce285< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22522,19 +22596,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ")" => ActionFn(1264); + // ClassPattern = MatchNameOrAttr, "(", OneOrMore, ")" => ActionFn(1269); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant79(__symbols); + let __sym2 = __pop_Variant78(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1264::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 103) + let __nt = super::__action1269::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 104) } - pub(crate) fn __reduce284< + pub(crate) fn __reduce286< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -22542,48 +22616,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClassPattern = MatchNameOrAttr, "(", ")" => ActionFn(1265); + // ClassPattern = MatchNameOrAttr, "(", ")" => ActionFn(1270); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1265::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 103) - } - pub(crate) fn __reduce285< - >( - mode: Mode, - __lookahead_start: Option<&TextSize>, - __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, - _: core::marker::PhantomData<()>, - ) -> (usize, usize) - { - // ClosedPattern = LiteralPattern => ActionFn(96); - let __sym0 = __pop_Variant36(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action96::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) - } - pub(crate) fn __reduce286< - >( - mode: Mode, - __lookahead_start: Option<&TextSize>, - __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, - _: core::marker::PhantomData<()>, - ) -> (usize, usize) - { - // ClosedPattern = CapturePattern => ActionFn(97); - let __sym0 = __pop_Variant36(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action97::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + let __nt = super::__action1270::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 104) } pub(crate) fn __reduce287< >( @@ -22593,13 +22635,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClosedPattern = StarPattern => ActionFn(98); - let __sym0 = __pop_Variant36(__symbols); + // ClosedPattern = LiteralPattern => ActionFn(98); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action98::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce288< >( @@ -22609,13 +22651,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClosedPattern = ValuePattern => ActionFn(99); - let __sym0 = __pop_Variant36(__symbols); + // ClosedPattern = CapturePattern => ActionFn(99); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action99::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce289< >( @@ -22625,13 +22667,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClosedPattern = SequencePattern => ActionFn(100); - let __sym0 = __pop_Variant36(__symbols); + // ClosedPattern = StarPattern => ActionFn(100); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action100::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce290< >( @@ -22641,13 +22683,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClosedPattern = MappingPattern => ActionFn(101); - let __sym0 = __pop_Variant36(__symbols); + // ClosedPattern = ValuePattern => ActionFn(101); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action101::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce291< >( @@ -22657,13 +22699,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ClosedPattern = ClassPattern => ActionFn(102); - let __sym0 = __pop_Variant36(__symbols); + // ClosedPattern = SequencePattern => ActionFn(102); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action102::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 104) + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce292< >( @@ -22673,12 +22715,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = FunctionArgument => ActionFn(1507); - let __sym0 = __pop_Variant32(__symbols); + // ClosedPattern = MappingPattern => ActionFn(103); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1507::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + let __nt = super::__action103::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); (1, 105) } pub(crate) fn __reduce293< @@ -22689,12 +22731,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = => ActionFn(1508); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action1508::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant52(__nt), __end)); - (0, 105) + // ClosedPattern = ClassPattern => ActionFn(104); + let __sym0 = __pop_Variant34(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action104::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 105) } pub(crate) fn __reduce294< >( @@ -22704,15 +22747,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = ( ",")+, FunctionArgument => ActionFn(1509); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant32(__symbols); - let __sym0 = __pop_Variant33(__symbols); + // Comma = FunctionArgument => ActionFn(1514); + let __sym0 = __pop_Variant30(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1509::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant52(__nt), __end)); - (2, 105) + let __end = __sym0.2; + let __nt = super::__action1514::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant51(__nt), __end)); + (1, 106) } pub(crate) fn __reduce295< >( @@ -22722,13 +22763,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = ( ",")+ => ActionFn(1510); - let __sym0 = __pop_Variant33(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action1510::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant52(__nt), __end)); - (1, 105) + // Comma = => ActionFn(1515); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action1515::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant51(__nt), __end)); + (0, 106) } pub(crate) fn __reduce296< >( @@ -22738,13 +22778,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = Pattern => ActionFn(1515); - let __sym0 = __pop_Variant36(__symbols); + // Comma = ( ",")+, FunctionArgument => ActionFn(1516); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant30(__symbols); + let __sym0 = __pop_Variant31(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action1515::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (1, 106) + let __end = __sym1.2; + let __nt = super::__action1516::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant51(__nt), __end)); + (2, 106) } pub(crate) fn __reduce297< >( @@ -22754,12 +22796,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = => ActionFn(1516); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action1516::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (0, 106) + // Comma = ( ",")+ => ActionFn(1517); + let __sym0 = __pop_Variant31(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action1517::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant51(__nt), __end)); + (1, 106) } pub(crate) fn __reduce298< >( @@ -22769,15 +22812,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = ( ",")+, Pattern => ActionFn(1517); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant36(__symbols); - let __sym0 = __pop_Variant37(__symbols); + // Comma = Pattern => ActionFn(1522); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1517::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (2, 106) + let __end = __sym0.2; + let __nt = super::__action1522::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (1, 107) } pub(crate) fn __reduce299< >( @@ -22787,13 +22828,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comma = ( ",")+ => ActionFn(1518); - let __sym0 = __pop_Variant37(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action1518::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (1, 106) + // Comma = => ActionFn(1523); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action1523::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (0, 107) } pub(crate) fn __reduce300< >( @@ -22803,13 +22843,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompFor = SingleForComprehension+ => ActionFn(222); - let __sym0 = __pop_Variant86(__symbols); + // Comma = ( ",")+, Pattern => ActionFn(1524); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant35(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action222::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant54(__nt), __end)); - (1, 107) + let __end = __sym1.2; + let __nt = super::__action1524::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (2, 107) } pub(crate) fn __reduce301< >( @@ -22819,13 +22861,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompFor? = CompFor => ActionFn(235); - let __sym0 = __pop_Variant54(__symbols); + // Comma = ( ",")+ => ActionFn(1525); + let __sym0 = __pop_Variant35(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action235::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant55(__nt), __end)); - (1, 108) + let __nt = super::__action1525::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (1, 107) } pub(crate) fn __reduce302< >( @@ -22835,12 +22877,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompFor? = => ActionFn(236); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action236::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant55(__nt), __end)); - (0, 108) + // CompFor = SingleForComprehension+ => ActionFn(226); + let __sym0 = __pop_Variant85(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action226::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant53(__nt), __end)); + (1, 108) } pub(crate) fn __reduce303< >( @@ -22850,12 +22893,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "==" => ActionFn(182); - let __sym0 = __pop_Variant0(__symbols); + // CompFor? = CompFor => ActionFn(239); + let __sym0 = __pop_Variant53(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action182::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); + let __nt = super::__action239::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant54(__nt), __end)); (1, 109) } pub(crate) fn __reduce304< @@ -22866,13 +22909,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "!=" => ActionFn(183); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action183::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + // CompFor? = => ActionFn(240); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action240::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant54(__nt), __end)); + (0, 109) } pub(crate) fn __reduce305< >( @@ -22882,13 +22924,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "<" => ActionFn(184); + // CompOp = "==" => ActionFn(186); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action184::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action186::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce306< >( @@ -22898,13 +22940,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "<=" => ActionFn(185); + // CompOp = "!=" => ActionFn(187); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action185::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action187::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce307< >( @@ -22914,13 +22956,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = ">" => ActionFn(186); + // CompOp = "<" => ActionFn(188); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action186::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action188::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce308< >( @@ -22930,13 +22972,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = ">=" => ActionFn(187); + // CompOp = "<=" => ActionFn(189); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action187::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action189::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce309< >( @@ -22946,13 +22988,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "in" => ActionFn(188); + // CompOp = ">" => ActionFn(190); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action188::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action190::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce310< >( @@ -22962,15 +23004,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "not", "in" => ActionFn(189); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant0(__symbols); + // CompOp = ">=" => ActionFn(191); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action189::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (2, 109) + let __end = __sym0.2; + let __nt = super::__action191::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce311< >( @@ -22980,13 +23020,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "is" => ActionFn(190); + // CompOp = "in" => ActionFn(192); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action190::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (1, 109) + let __nt = super::__action192::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce312< >( @@ -22996,15 +23036,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompOp = "is", "not" => ActionFn(191); + // CompOp = "not", "in" => ActionFn(193); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action191::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant56(__nt), __end)); - (2, 109) + let __nt = super::__action193::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (2, 110) } pub(crate) fn __reduce313< >( @@ -23014,15 +23054,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comparison<"all"> = Expression<"all">, (CompOp Expression<"all">)+ => ActionFn(1266); - assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant46(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // CompOp = "is" => ActionFn(194); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action1266::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 110) + let __end = __sym0.2; + let __nt = super::__action194::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (1, 110) } pub(crate) fn __reduce314< >( @@ -23032,13 +23070,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comparison<"all"> = Expression<"all"> => ActionFn(487); - let __sym0 = __pop_Variant16(__symbols); + // CompOp = "is", "not" => ActionFn(195); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action487::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 110) + let __end = __sym1.2; + let __nt = super::__action195::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant55(__nt), __end)); + (2, 110) } pub(crate) fn __reduce315< >( @@ -23048,14 +23088,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comparison<"no-withitems"> = Expression<"all">, (CompOp Expression<"all">)+ => ActionFn(1267); + // Comparison<"all"> = Expression<"all">, (CompOp Expression<"all">)+ => ActionFn(1271); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant46(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant44(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1267::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action1271::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (2, 111) } pub(crate) fn __reduce316< @@ -23066,12 +23106,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Comparison<"no-withitems"> = Expression<"no-withitems"> => ActionFn(496); - let __sym0 = __pop_Variant16(__symbols); + // Comparison<"all"> = Expression<"all"> => ActionFn(492); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action496::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + let __nt = super::__action492::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 111) } pub(crate) fn __reduce317< @@ -23082,13 +23122,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = MatchStatement => ActionFn(75); - let __sym0 = __pop_Variant38(__symbols); + // Comparison<"no-withitems"> = Expression<"all">, (CompOp Expression<"all">)+ => ActionFn(1272); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant44(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action75::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + let __end = __sym1.2; + let __nt = super::__action1272::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 112) } pub(crate) fn __reduce318< >( @@ -23098,12 +23140,12 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = IfStatement => ActionFn(76); - let __sym0 = __pop_Variant38(__symbols); + // Comparison<"no-withitems"> = Expression<"no-withitems"> => ActionFn(503); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action76::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); + let __nt = super::__action503::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); (1, 112) } pub(crate) fn __reduce319< @@ -23114,13 +23156,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = WhileStatement => ActionFn(77); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = MatchStatement => ActionFn(77); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action77::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce320< >( @@ -23130,13 +23172,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = ForStatement => ActionFn(78); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = IfStatement => ActionFn(78); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action78::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce321< >( @@ -23146,13 +23188,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = TryStatement => ActionFn(79); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = WhileStatement => ActionFn(79); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action79::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce322< >( @@ -23162,13 +23204,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = WithStatement => ActionFn(80); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = ForStatement => ActionFn(80); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action80::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce323< >( @@ -23178,13 +23220,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = FuncDef => ActionFn(81); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = TryStatement => ActionFn(81); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action81::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce324< >( @@ -23194,13 +23236,13 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // CompoundStatement = ClassDef => ActionFn(82); - let __sym0 = __pop_Variant38(__symbols); + // CompoundStatement = WithStatement => ActionFn(82); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action82::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 112) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) } pub(crate) fn __reduce325< >( @@ -23210,17 +23252,49 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ComprehensionIf = "if", ExpressionNoCond => ActionFn(225); + // CompoundStatement = FuncDef => ActionFn(83); + let __sym0 = __pop_Variant36(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action83::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) + } + pub(crate) fn __reduce326< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // CompoundStatement = ClassDef => ActionFn(84); + let __sym0 = __pop_Variant36(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action84::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 113) + } + pub(crate) fn __reduce327< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // ComprehensionIf = "if", ExpressionNoCond => ActionFn(229); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action225::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 113) + let __nt = super::__action229::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 114) } - pub(crate) fn __reduce326< + pub(crate) fn __reduce328< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23228,14 +23302,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ComprehensionIf* = => ActionFn(238); + // ComprehensionIf* = => ActionFn(242); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action238::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (0, 114) + let __nt = super::__action242::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (0, 115) } - pub(crate) fn __reduce327< + pub(crate) fn __reduce329< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23243,15 +23317,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ComprehensionIf* = ComprehensionIf+ => ActionFn(239); - let __sym0 = __pop_Variant18(__symbols); + // ComprehensionIf* = ComprehensionIf+ => ActionFn(243); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action239::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (1, 114) + let __nt = super::__action243::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (1, 115) } - pub(crate) fn __reduce328< + pub(crate) fn __reduce330< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23259,15 +23333,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ComprehensionIf+ = ComprehensionIf => ActionFn(436); - let __sym0 = __pop_Variant16(__symbols); + // ComprehensionIf+ = ComprehensionIf => ActionFn(441); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action436::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (1, 115) + let __nt = super::__action441::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (1, 116) } - pub(crate) fn __reduce329< + pub(crate) fn __reduce331< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23275,17 +23349,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ComprehensionIf+ = ComprehensionIf+, ComprehensionIf => ActionFn(437); + // ComprehensionIf+ = ComprehensionIf+, ComprehensionIf => ActionFn(442); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action437::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant18(__nt), __end)); - (2, 115) + let __nt = super::__action442::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant16(__nt), __end)); + (2, 116) } - pub(crate) fn __reduce330< + pub(crate) fn __reduce332< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23293,15 +23367,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Constant = int => ActionFn(231); + // Constant = int => ActionFn(235); let __sym0 = __pop_Variant3(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action231::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant57(__nt), __end)); - (1, 116) + let __nt = super::__action235::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant56(__nt), __end)); + (1, 117) } - pub(crate) fn __reduce331< + pub(crate) fn __reduce333< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23309,15 +23383,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Constant = float => ActionFn(232); + // Constant = float => ActionFn(236); let __sym0 = __pop_Variant2(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action232::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant57(__nt), __end)); - (1, 116) + let __nt = super::__action236::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant56(__nt), __end)); + (1, 117) } - pub(crate) fn __reduce332< + pub(crate) fn __reduce334< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23325,15 +23399,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Constant = complex => ActionFn(233); + // Constant = complex => ActionFn(237); let __sym0 = __pop_Variant1(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action233::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant57(__nt), __end)); - (1, 116) + let __nt = super::__action237::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant56(__nt), __end)); + (1, 117) } - pub(crate) fn __reduce333< + pub(crate) fn __reduce335< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23341,15 +23415,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ConstantAtom = Constant => ActionFn(1268); - let __sym0 = __pop_Variant57(__symbols); + // ConstantAtom = Constant => ActionFn(1273); + let __sym0 = __pop_Variant56(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1268::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 117) + let __nt = super::__action1273::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 118) } - pub(crate) fn __reduce334< + pub(crate) fn __reduce336< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23357,15 +23431,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ConstantExpr = ConstantAtom => ActionFn(110); - let __sym0 = __pop_Variant16(__symbols); + // ConstantExpr = ConstantAtom => ActionFn(112); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action110::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 118) + let __nt = super::__action112::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 119) } - pub(crate) fn __reduce335< + pub(crate) fn __reduce337< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23373,17 +23447,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ConstantExpr = "-", ConstantAtom => ActionFn(1269); + // ConstantExpr = "-", ConstantAtom => ActionFn(1274); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1269::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 118) + let __nt = super::__action1274::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 119) } - pub(crate) fn __reduce336< + pub(crate) fn __reduce338< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23391,18 +23465,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Decorator = "@", NamedExpressionTest, "\n" => ActionFn(1270); + // Decorator = "@", NamedExpressionTest, "\n" => ActionFn(1275); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1270::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant58(__nt), __end)); - (3, 119) + let __nt = super::__action1275::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant57(__nt), __end)); + (3, 120) } - pub(crate) fn __reduce337< + pub(crate) fn __reduce339< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23410,14 +23484,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Decorator* = => ActionFn(287); + // Decorator* = => ActionFn(288); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action287::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant59(__nt), __end)); - (0, 120) + let __nt = super::__action288::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant58(__nt), __end)); + (0, 121) } - pub(crate) fn __reduce338< + pub(crate) fn __reduce340< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23425,15 +23499,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Decorator* = Decorator+ => ActionFn(288); - let __sym0 = __pop_Variant59(__symbols); + // Decorator* = Decorator+ => ActionFn(289); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action288::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant59(__nt), __end)); - (1, 120) + let __nt = super::__action289::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant58(__nt), __end)); + (1, 121) } - pub(crate) fn __reduce339< + pub(crate) fn __reduce341< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23441,15 +23515,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Decorator+ = Decorator => ActionFn(409); - let __sym0 = __pop_Variant58(__symbols); + // Decorator+ = Decorator => ActionFn(416); + let __sym0 = __pop_Variant57(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action409::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant59(__nt), __end)); - (1, 121) + let __nt = super::__action416::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant58(__nt), __end)); + (1, 122) } - pub(crate) fn __reduce340< + pub(crate) fn __reduce342< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23457,17 +23531,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Decorator+ = Decorator+, Decorator => ActionFn(410); + // Decorator+ = Decorator+, Decorator => ActionFn(417); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant58(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym1 = __pop_Variant57(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action410::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant59(__nt), __end)); - (2, 121) + let __nt = super::__action417::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant58(__nt), __end)); + (2, 122) } - pub(crate) fn __reduce341< + pub(crate) fn __reduce343< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23475,17 +23549,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DelStatement = "del", ExpressionList2 => ActionFn(1271); + // DelStatement = "del", ExpressionList2 => ActionFn(1276); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1271::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 122) + let __nt = super::__action1276::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 123) } - pub(crate) fn __reduce342< + pub(crate) fn __reduce344< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23493,15 +23567,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictElement = DictEntry => ActionFn(213); - let __sym0 = __pop_Variant61(__symbols); + // DictElement = DictEntry => ActionFn(217); + let __sym0 = __pop_Variant60(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action213::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant60(__nt), __end)); - (1, 123) + let __nt = super::__action217::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant59(__nt), __end)); + (1, 124) } - pub(crate) fn __reduce343< + pub(crate) fn __reduce345< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23509,17 +23583,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictElement = "**", Expression<"all"> => ActionFn(214); + // DictElement = "**", Expression<"all"> => ActionFn(218); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action214::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant60(__nt), __end)); - (2, 123) + let __nt = super::__action218::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant59(__nt), __end)); + (2, 124) } - pub(crate) fn __reduce344< + pub(crate) fn __reduce346< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23527,18 +23601,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictEntry = Test<"all">, ":", Test<"all"> => ActionFn(212); + // DictEntry = Test<"all">, ":", Test<"all"> => ActionFn(216); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action212::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant61(__nt), __end)); - (3, 124) + let __nt = super::__action216::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant60(__nt), __end)); + (3, 125) } - pub(crate) fn __reduce345< + pub(crate) fn __reduce347< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23546,17 +23620,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictLiteralValues = OneOrMore, "," => ActionFn(598); + // DictLiteralValues = OneOrMore, "," => ActionFn(603); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant62(__symbols); + let __sym0 = __pop_Variant61(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action598::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant62(__nt), __end)); - (2, 125) + let __nt = super::__action603::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant61(__nt), __end)); + (2, 126) } - pub(crate) fn __reduce346< + pub(crate) fn __reduce348< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23564,15 +23638,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictLiteralValues = OneOrMore => ActionFn(599); - let __sym0 = __pop_Variant62(__symbols); + // DictLiteralValues = OneOrMore => ActionFn(604); + let __sym0 = __pop_Variant61(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action599::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant62(__nt), __end)); - (1, 125) + let __nt = super::__action604::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant61(__nt), __end)); + (1, 126) } - pub(crate) fn __reduce347< + pub(crate) fn __reduce349< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23580,15 +23654,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictLiteralValues? = DictLiteralValues => ActionFn(540); - let __sym0 = __pop_Variant62(__symbols); + // DictLiteralValues? = DictLiteralValues => ActionFn(543); + let __sym0 = __pop_Variant61(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action540::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant63(__nt), __end)); - (1, 126) + let __nt = super::__action543::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant62(__nt), __end)); + (1, 127) } - pub(crate) fn __reduce348< + pub(crate) fn __reduce350< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23596,14 +23670,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DictLiteralValues? = => ActionFn(541); + // DictLiteralValues? = => ActionFn(544); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action541::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant63(__nt), __end)); - (0, 126) + let __nt = super::__action544::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant62(__nt), __end)); + (0, 127) } - pub(crate) fn __reduce349< + pub(crate) fn __reduce351< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23611,15 +23685,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DottedName = name => ActionFn(1272); + // DottedName = name => ActionFn(1277); let __sym0 = __pop_Variant5(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1272::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant24(__nt), __end)); - (1, 127) + let __nt = super::__action1277::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant22(__nt), __end)); + (1, 128) } - pub(crate) fn __reduce350< + pub(crate) fn __reduce352< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23627,17 +23701,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DottedName = name, ("." Identifier)+ => ActionFn(1273); + // DottedName = name, ("." Identifier)+ => ActionFn(1278); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant22(__symbols); + let __sym1 = __pop_Variant20(__symbols); let __sym0 = __pop_Variant5(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1273::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant24(__nt), __end)); - (2, 127) + let __nt = super::__action1278::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant22(__nt), __end)); + (2, 128) } - pub(crate) fn __reduce351< + pub(crate) fn __reduce353< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23645,18 +23719,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DoubleStarTypedParameter = Identifier, ":", Test<"all"> => ActionFn(1274); + // DoubleStarTypedParameter = Identifier, ":", Test<"all"> => ActionFn(1279); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1274::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant64(__nt), __end)); - (3, 128) + let __nt = super::__action1279::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant63(__nt), __end)); + (3, 129) } - pub(crate) fn __reduce352< + pub(crate) fn __reduce354< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23664,15 +23738,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DoubleStarTypedParameter = Identifier => ActionFn(1275); - let __sym0 = __pop_Variant24(__symbols); + // DoubleStarTypedParameter = Identifier => ActionFn(1280); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1275::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant64(__nt), __end)); - (1, 128) + let __nt = super::__action1280::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant63(__nt), __end)); + (1, 129) } - pub(crate) fn __reduce353< + pub(crate) fn __reduce355< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23680,15 +23754,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DoubleStarTypedParameter? = DoubleStarTypedParameter => ActionFn(474); - let __sym0 = __pop_Variant64(__symbols); + // DoubleStarTypedParameter? = DoubleStarTypedParameter => ActionFn(477); + let __sym0 = __pop_Variant63(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action474::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (1, 129) + let __nt = super::__action477::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (1, 130) } - pub(crate) fn __reduce354< + pub(crate) fn __reduce356< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23696,14 +23770,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // DoubleStarTypedParameter? = => ActionFn(475); + // DoubleStarTypedParameter? = => ActionFn(478); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action475::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (0, 129) + let __nt = super::__action478::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (0, 130) } - pub(crate) fn __reduce355< + pub(crate) fn __reduce357< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23711,19 +23785,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExceptClause = "except", Test<"all">, ":", Suite => ActionFn(1685); + // ExceptClause = "except", Test<"all">, ":", Suite => ActionFn(1692); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1685::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant66(__nt), __end)); - (4, 130) + let __nt = super::__action1692::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant65(__nt), __end)); + (4, 131) } - pub(crate) fn __reduce356< + pub(crate) fn __reduce358< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23731,18 +23805,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExceptClause = "except", ":", Suite => ActionFn(1686); + // ExceptClause = "except", ":", Suite => ActionFn(1693); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1686::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant66(__nt), __end)); - (3, 130) + let __nt = super::__action1693::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant65(__nt), __end)); + (3, 131) } - pub(crate) fn __reduce357< + pub(crate) fn __reduce359< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23750,21 +23824,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExceptClause = "except", Test<"all">, "as", Identifier, ":", Suite => ActionFn(1182); + // ExceptClause = "except", Test<"all">, "as", Identifier, ":", Suite => ActionFn(1186); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant22(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1182::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant66(__nt), __end)); - (6, 130) + let __nt = super::__action1186::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant65(__nt), __end)); + (6, 131) } - pub(crate) fn __reduce358< + pub(crate) fn __reduce360< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23773,14 +23847,14 @@ mod __parse__Top { ) -> (usize, usize) { // ExceptClause+ = ExceptClause => ActionFn(312); - let __sym0 = __pop_Variant66(__symbols); + let __sym0 = __pop_Variant65(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action312::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant67(__nt), __end)); - (1, 131) + __symbols.push((__start, __Symbol::Variant66(__nt), __end)); + (1, 132) } - pub(crate) fn __reduce359< + pub(crate) fn __reduce361< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23790,15 +23864,15 @@ mod __parse__Top { { // ExceptClause+ = ExceptClause+, ExceptClause => ActionFn(313); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant66(__symbols); - let __sym0 = __pop_Variant67(__symbols); + let __sym1 = __pop_Variant65(__symbols); + let __sym0 = __pop_Variant66(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action313::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant67(__nt), __end)); - (2, 131) + __symbols.push((__start, __Symbol::Variant66(__nt), __end)); + (2, 132) } - pub(crate) fn __reduce360< + pub(crate) fn __reduce362< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23806,20 +23880,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExceptStarClause = "except", "*", Test<"all">, ":", Suite => ActionFn(787); + // ExceptStarClause = "except", "*", Test<"all">, ":", Suite => ActionFn(789); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action787::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant66(__nt), __end)); - (5, 132) + let __nt = super::__action789::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant65(__nt), __end)); + (5, 133) } - pub(crate) fn __reduce361< + pub(crate) fn __reduce363< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23827,22 +23901,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExceptStarClause = "except", "*", Test<"all">, "as", Identifier, ":", Suite => ActionFn(1183); + // ExceptStarClause = "except", "*", Test<"all">, "as", Identifier, ":", Suite => ActionFn(1187); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant22(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1183::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant66(__nt), __end)); - (7, 132) + let __nt = super::__action1187::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant65(__nt), __end)); + (7, 133) } - pub(crate) fn __reduce362< + pub(crate) fn __reduce364< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23851,14 +23925,14 @@ mod __parse__Top { ) -> (usize, usize) { // ExceptStarClause+ = ExceptStarClause => ActionFn(307); - let __sym0 = __pop_Variant66(__symbols); + let __sym0 = __pop_Variant65(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action307::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant67(__nt), __end)); - (1, 133) + __symbols.push((__start, __Symbol::Variant66(__nt), __end)); + (1, 134) } - pub(crate) fn __reduce363< + pub(crate) fn __reduce365< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23868,15 +23942,15 @@ mod __parse__Top { { // ExceptStarClause+ = ExceptStarClause+, ExceptStarClause => ActionFn(308); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant66(__symbols); - let __sym0 = __pop_Variant67(__symbols); + let __sym1 = __pop_Variant65(__symbols); + let __sym0 = __pop_Variant66(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action308::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant67(__nt), __end)); - (2, 133) + __symbols.push((__start, __Symbol::Variant66(__nt), __end)); + (2, 134) } - pub(crate) fn __reduce364< + pub(crate) fn __reduce366< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23884,18 +23958,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Expression<"all"> = Expression<"all">, "|", XorExpression<"all"> => ActionFn(1276); + // Expression<"all"> = Expression<"all">, "|", XorExpression<"all"> => ActionFn(1281); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1276::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 134) + let __nt = super::__action1281::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 135) } - pub(crate) fn __reduce365< + pub(crate) fn __reduce367< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23903,15 +23977,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Expression<"all"> = XorExpression<"all"> => ActionFn(249); - let __sym0 = __pop_Variant16(__symbols); + // Expression<"all"> = XorExpression<"all"> => ActionFn(353); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action249::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 134) + let __nt = super::__action353::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 135) } - pub(crate) fn __reduce366< + pub(crate) fn __reduce368< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23919,18 +23993,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Expression<"no-withitems"> = Expression<"all">, "|", XorExpression<"all"> => ActionFn(1277); + // Expression<"no-withitems"> = Expression<"all">, "|", XorExpression<"all"> => ActionFn(1282); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1277::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 135) + let __nt = super::__action1282::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 136) } - pub(crate) fn __reduce367< + pub(crate) fn __reduce369< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23938,15 +24012,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Expression<"no-withitems"> = XorExpression<"no-withitems"> => ActionFn(502); - let __sym0 = __pop_Variant16(__symbols); + // Expression<"no-withitems"> = XorExpression<"no-withitems"> => ActionFn(505); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action502::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 135) + let __nt = super::__action505::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 136) } - pub(crate) fn __reduce368< + pub(crate) fn __reduce370< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23954,15 +24028,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionList = GenericList => ActionFn(218); - let __sym0 = __pop_Variant16(__symbols); + // ExpressionList = GenericList => ActionFn(222); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action218::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 136) + let __nt = super::__action222::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 137) } - pub(crate) fn __reduce369< + pub(crate) fn __reduce371< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23970,17 +24044,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionList2 = OneOrMore, "," => ActionFn(600); + // ExpressionList2 = OneOrMore, "," => ActionFn(605); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action600::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (2, 137) + let __nt = super::__action605::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (2, 138) } - pub(crate) fn __reduce370< + pub(crate) fn __reduce372< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -23988,15 +24062,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionList2 = OneOrMore => ActionFn(601); - let __sym0 = __pop_Variant34(__symbols); + // ExpressionList2 = OneOrMore => ActionFn(606); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action601::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 137) + let __nt = super::__action606::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 138) } - pub(crate) fn __reduce371< + pub(crate) fn __reduce373< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24004,15 +24078,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionNoCond = OrTest<"all"> => ActionFn(224); - let __sym0 = __pop_Variant16(__symbols); + // ExpressionNoCond = OrTest<"all"> => ActionFn(228); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action224::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 138) + let __nt = super::__action228::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 139) } - pub(crate) fn __reduce372< + pub(crate) fn __reduce374< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24020,15 +24094,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionOrStarExpression = Expression<"all"> => ActionFn(216); - let __sym0 = __pop_Variant16(__symbols); + // ExpressionOrStarExpression = Expression<"all"> => ActionFn(220); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action216::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 139) + let __nt = super::__action220::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 140) } - pub(crate) fn __reduce373< + pub(crate) fn __reduce375< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24036,15 +24110,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionOrStarExpression = StarExpr => ActionFn(217); - let __sym0 = __pop_Variant16(__symbols); + // ExpressionOrStarExpression = StarExpr => ActionFn(221); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action217::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 139) + let __nt = super::__action221::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 140) } - pub(crate) fn __reduce374< + pub(crate) fn __reduce376< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24052,15 +24126,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionStatement = GenericList => ActionFn(1710); - let __sym0 = __pop_Variant16(__symbols); + // ExpressionStatement = GenericList => ActionFn(1717); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1710::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 140) + let __nt = super::__action1717::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 141) } - pub(crate) fn __reduce375< + pub(crate) fn __reduce377< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24068,17 +24142,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionStatement = GenericList, AssignSuffix+ => ActionFn(1711); + // ExpressionStatement = GenericList, AssignSuffix+ => ActionFn(1718); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant18(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1711::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 140) + let __nt = super::__action1718::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 141) } - pub(crate) fn __reduce376< + pub(crate) fn __reduce378< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24086,18 +24160,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionStatement = GenericList, AugAssign, TestListOrYieldExpr => ActionFn(1712); + // ExpressionStatement = GenericList, AugAssign, TestListOrYieldExpr => ActionFn(1719); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1712::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (3, 140) + let __nt = super::__action1719::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (3, 141) } - pub(crate) fn __reduce377< + pub(crate) fn __reduce379< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24105,19 +24179,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionStatement = Test<"all">, ":", Test<"all">, AssignSuffix => ActionFn(1505); + // ExpressionStatement = Test<"all">, ":", Test<"all">, AssignSuffix => ActionFn(1512); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1505::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 140) + let __nt = super::__action1512::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 141) } - pub(crate) fn __reduce378< + pub(crate) fn __reduce380< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24125,18 +24199,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ExpressionStatement = Test<"all">, ":", Test<"all"> => ActionFn(1506); + // ExpressionStatement = Test<"all">, ":", Test<"all"> => ActionFn(1513); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1506::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (3, 140) + let __nt = super::__action1513::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (3, 141) } - pub(crate) fn __reduce379< + pub(crate) fn __reduce381< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24144,17 +24218,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Factor<"all"> = UnaryOp, Factor<"all"> => ActionFn(1281); + // Factor<"all"> = UnaryOp, Factor<"all"> => ActionFn(1286); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant93(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1281::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 141) + let __nt = super::__action1286::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 142) } - pub(crate) fn __reduce380< + pub(crate) fn __reduce382< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24162,15 +24236,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Factor<"all"> = Power<"all"> => ActionFn(500); - let __sym0 = __pop_Variant16(__symbols); + // Factor<"all"> = Power<"all"> => ActionFn(507); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action500::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 141) + let __nt = super::__action507::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 142) } - pub(crate) fn __reduce381< + pub(crate) fn __reduce383< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24178,17 +24252,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Factor<"no-withitems"> = UnaryOp, Factor<"all"> => ActionFn(1282); + // Factor<"no-withitems"> = UnaryOp, Factor<"all"> => ActionFn(1287); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant93(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1282::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 142) + let __nt = super::__action1287::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 143) } - pub(crate) fn __reduce382< + pub(crate) fn __reduce384< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24196,15 +24270,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Factor<"no-withitems"> = Power<"no-withitems"> => ActionFn(553); - let __sym0 = __pop_Variant16(__symbols); + // Factor<"no-withitems"> = Power<"no-withitems"> => ActionFn(556); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action553::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 142) + let __nt = super::__action556::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 143) } - pub(crate) fn __reduce383< + pub(crate) fn __reduce385< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24212,15 +24286,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = "break" => ActionFn(1283); + // FlowStatement = "break" => ActionFn(1288); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1283::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 143) + let __nt = super::__action1288::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 144) } - pub(crate) fn __reduce384< + pub(crate) fn __reduce386< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24228,15 +24302,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = "continue" => ActionFn(1284); + // FlowStatement = "continue" => ActionFn(1289); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1284::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 143) + let __nt = super::__action1289::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 144) } - pub(crate) fn __reduce385< + pub(crate) fn __reduce387< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24244,17 +24318,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = "return", GenericList => ActionFn(1706); + // FlowStatement = "return", GenericList => ActionFn(1713); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1706::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 143) + let __nt = super::__action1713::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 144) } - pub(crate) fn __reduce386< + pub(crate) fn __reduce388< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24262,15 +24336,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = "return" => ActionFn(1707); + // FlowStatement = "return" => ActionFn(1714); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1707::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 143) + let __nt = super::__action1714::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 144) } - pub(crate) fn __reduce387< + pub(crate) fn __reduce389< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24278,15 +24352,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = YieldExpr => ActionFn(1286); - let __sym0 = __pop_Variant16(__symbols); + // FlowStatement = YieldExpr => ActionFn(1291); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1286::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 143) + let __nt = super::__action1291::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 144) } - pub(crate) fn __reduce388< + pub(crate) fn __reduce390< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24294,15 +24368,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FlowStatement = RaiseStatement => ActionFn(56); - let __sym0 = __pop_Variant38(__symbols); + // FlowStatement = RaiseStatement => ActionFn(57); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action56::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 143) + let __nt = super::__action57::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 144) } - pub(crate) fn __reduce389< + pub(crate) fn __reduce391< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24310,25 +24384,25 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ForStatement = "async", "for", ExpressionList, "in", GenericList, ":", Suite, "else", ":", Suite => ActionFn(1697); + // ForStatement = "async", "for", ExpressionList, "in", GenericList, ":", Suite, "else", ":", Suite => ActionFn(1704); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant26(__symbols); + let __sym9 = __pop_Variant24(__symbols); let __sym8 = __pop_Variant0(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = super::__action1697::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (10, 144) + let __nt = super::__action1704::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (10, 145) } - pub(crate) fn __reduce390< + pub(crate) fn __reduce392< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24336,22 +24410,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ForStatement = "async", "for", ExpressionList, "in", GenericList, ":", Suite => ActionFn(1698); + // ForStatement = "async", "for", ExpressionList, "in", GenericList, ":", Suite => ActionFn(1705); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1698::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 144) + let __nt = super::__action1705::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 145) } - pub(crate) fn __reduce391< + pub(crate) fn __reduce393< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24359,24 +24433,24 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ForStatement = "for", ExpressionList, "in", GenericList, ":", Suite, "else", ":", Suite => ActionFn(1699); + // ForStatement = "for", ExpressionList, "in", GenericList, ":", Suite, "else", ":", Suite => ActionFn(1706); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant26(__symbols); + let __sym8 = __pop_Variant24(__symbols); let __sym7 = __pop_Variant0(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = super::__action1699::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (9, 144) + let __nt = super::__action1706::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (9, 145) } - pub(crate) fn __reduce392< + pub(crate) fn __reduce394< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24384,21 +24458,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ForStatement = "for", ExpressionList, "in", GenericList, ":", Suite => ActionFn(1700); + // ForStatement = "for", ExpressionList, "in", GenericList, ":", Suite => ActionFn(1707); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1700::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 144) + let __nt = super::__action1707::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 145) } - pub(crate) fn __reduce393< + pub(crate) fn __reduce395< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24406,24 +24480,24 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "async", "def", Identifier, TypeParamList, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1721); + // FuncDef = "async", "def", Identifier, TypeParams, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1728); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant26(__symbols); + let __sym8 = __pop_Variant24(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant16(__symbols); + let __sym6 = __pop_Variant14(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = super::__action1721::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (9, 145) + let __nt = super::__action1728::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (9, 146) } - pub(crate) fn __reduce394< + pub(crate) fn __reduce396< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24431,23 +24505,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "async", "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1722); + // FuncDef = "async", "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1729); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); + let __sym7 = __pop_Variant24(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant16(__symbols); + let __sym5 = __pop_Variant14(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action1722::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 145) + let __nt = super::__action1729::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 146) } - pub(crate) fn __reduce395< + pub(crate) fn __reduce397< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24455,25 +24529,25 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "async", "def", Identifier, TypeParamList, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1723); + // FuncDef = Decorator+, "async", "def", Identifier, TypeParams, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1730); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant26(__symbols); + let __sym9 = __pop_Variant24(__symbols); let __sym8 = __pop_Variant0(__symbols); - let __sym7 = __pop_Variant16(__symbols); + let __sym7 = __pop_Variant14(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant47(__symbols); - let __sym4 = __pop_Variant82(__symbols); - let __sym3 = __pop_Variant24(__symbols); + let __sym5 = __pop_Variant45(__symbols); + let __sym4 = __pop_Variant91(__symbols); + let __sym3 = __pop_Variant22(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = super::__action1723::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (10, 145) + let __nt = super::__action1730::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (10, 146) } - pub(crate) fn __reduce396< + pub(crate) fn __reduce398< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24481,24 +24555,24 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "async", "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1724); + // FuncDef = Decorator+, "async", "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1731); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant26(__symbols); + let __sym8 = __pop_Variant24(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant16(__symbols); + let __sym6 = __pop_Variant14(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant22(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = super::__action1724::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (9, 145) + let __nt = super::__action1731::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (9, 146) } - pub(crate) fn __reduce397< + pub(crate) fn __reduce399< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24506,22 +24580,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "async", "def", Identifier, TypeParamList, Parameters, ":", Suite => ActionFn(1725); + // FuncDef = "async", "def", Identifier, TypeParams, Parameters, ":", Suite => ActionFn(1732); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1725::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 145) + let __nt = super::__action1732::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 146) } - pub(crate) fn __reduce398< + pub(crate) fn __reduce400< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24529,21 +24603,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "async", "def", Identifier, Parameters, ":", Suite => ActionFn(1726); + // FuncDef = "async", "def", Identifier, Parameters, ":", Suite => ActionFn(1733); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1726::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 145) + let __nt = super::__action1733::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 146) } - pub(crate) fn __reduce399< + pub(crate) fn __reduce401< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24551,23 +24625,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "async", "def", Identifier, TypeParamList, Parameters, ":", Suite => ActionFn(1727); + // FuncDef = Decorator+, "async", "def", Identifier, TypeParams, Parameters, ":", Suite => ActionFn(1734); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); + let __sym7 = __pop_Variant24(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant47(__symbols); - let __sym4 = __pop_Variant82(__symbols); - let __sym3 = __pop_Variant24(__symbols); + let __sym5 = __pop_Variant45(__symbols); + let __sym4 = __pop_Variant91(__symbols); + let __sym3 = __pop_Variant22(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action1727::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 145) + let __nt = super::__action1734::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 146) } - pub(crate) fn __reduce400< + pub(crate) fn __reduce402< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24575,22 +24649,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "async", "def", Identifier, Parameters, ":", Suite => ActionFn(1728); + // FuncDef = Decorator+, "async", "def", Identifier, Parameters, ":", Suite => ActionFn(1735); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant22(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1728::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 145) + let __nt = super::__action1735::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 146) } - pub(crate) fn __reduce401< + pub(crate) fn __reduce403< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24598,23 +24672,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "def", Identifier, TypeParamList, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1729); + // FuncDef = "def", Identifier, TypeParams, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1736); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); + let __sym7 = __pop_Variant24(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant16(__symbols); + let __sym5 = __pop_Variant14(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant82(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant91(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action1729::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 145) + let __nt = super::__action1736::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 146) } - pub(crate) fn __reduce402< + pub(crate) fn __reduce404< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24622,22 +24696,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1730); + // FuncDef = "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1737); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant47(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant45(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1730::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 145) + let __nt = super::__action1737::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 146) } - pub(crate) fn __reduce403< + pub(crate) fn __reduce405< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24645,24 +24719,24 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "def", Identifier, TypeParamList, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1731); + // FuncDef = Decorator+, "def", Identifier, TypeParams, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1738); assert!(__symbols.len() >= 9); - let __sym8 = __pop_Variant26(__symbols); + let __sym8 = __pop_Variant24(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant16(__symbols); + let __sym6 = __pop_Variant14(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym8.2; - let __nt = super::__action1731::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (9, 145) + let __nt = super::__action1738::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (9, 146) } - pub(crate) fn __reduce404< + pub(crate) fn __reduce406< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24670,23 +24744,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1732); + // FuncDef = Decorator+, "def", Identifier, Parameters, "->", Test<"all">, ":", Suite => ActionFn(1739); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); + let __sym7 = __pop_Variant24(__symbols); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant16(__symbols); + let __sym5 = __pop_Variant14(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action1732::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 145) + let __nt = super::__action1739::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 146) } - pub(crate) fn __reduce405< + pub(crate) fn __reduce407< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24694,21 +24768,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "def", Identifier, TypeParamList, Parameters, ":", Suite => ActionFn(1733); + // FuncDef = "def", Identifier, TypeParams, Parameters, ":", Suite => ActionFn(1740); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant82(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant91(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1733::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 145) + let __nt = super::__action1740::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 146) } - pub(crate) fn __reduce406< + pub(crate) fn __reduce408< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24716,20 +24790,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = "def", Identifier, Parameters, ":", Suite => ActionFn(1734); + // FuncDef = "def", Identifier, Parameters, ":", Suite => ActionFn(1741); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant47(__symbols); - let __sym1 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant45(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1734::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 145) + let __nt = super::__action1741::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 146) } - pub(crate) fn __reduce407< + pub(crate) fn __reduce409< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24737,22 +24811,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "def", Identifier, TypeParamList, Parameters, ":", Suite => ActionFn(1735); + // FuncDef = Decorator+, "def", Identifier, TypeParams, Parameters, ":", Suite => ActionFn(1742); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant47(__symbols); - let __sym3 = __pop_Variant82(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant45(__symbols); + let __sym3 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1735::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 145) + let __nt = super::__action1742::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 146) } - pub(crate) fn __reduce408< + pub(crate) fn __reduce410< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24760,21 +24834,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FuncDef = Decorator+, "def", Identifier, Parameters, ":", Suite => ActionFn(1736); + // FuncDef = Decorator+, "def", Identifier, Parameters, ":", Suite => ActionFn(1743); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant47(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym3 = __pop_Variant45(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant59(__symbols); + let __sym0 = __pop_Variant58(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1736::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 145) + let __nt = super::__action1743::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 146) } - pub(crate) fn __reduce409< + pub(crate) fn __reduce411< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24782,17 +24856,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument = NamedExpressionTest, CompFor => ActionFn(1523); + // FunctionArgument = NamedExpressionTest, CompFor => ActionFn(1530); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant54(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant53(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1523::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); - (2, 146) + let __nt = super::__action1530::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + (2, 147) } - pub(crate) fn __reduce410< + pub(crate) fn __reduce412< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24800,15 +24874,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument = NamedExpressionTest => ActionFn(1524); - let __sym0 = __pop_Variant16(__symbols); + // FunctionArgument = NamedExpressionTest => ActionFn(1531); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1524::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); - (1, 146) + let __nt = super::__action1531::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + (1, 147) } - pub(crate) fn __reduce411< + pub(crate) fn __reduce413< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24816,18 +24890,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument = Identifier, "=", Test<"all"> => ActionFn(1288); + // FunctionArgument = Identifier, "=", Test<"all"> => ActionFn(1293); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1288::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); - (3, 146) + let __nt = super::__action1293::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + (3, 147) } - pub(crate) fn __reduce412< + pub(crate) fn __reduce414< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24835,17 +24909,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument = "*", Test<"all"> => ActionFn(1289); + // FunctionArgument = "*", Test<"all"> => ActionFn(1294); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1289::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); - (2, 146) + let __nt = super::__action1294::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + (2, 147) } - pub(crate) fn __reduce413< + pub(crate) fn __reduce415< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24853,17 +24927,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument = "**", Test<"all"> => ActionFn(1290); + // FunctionArgument = "**", Test<"all"> => ActionFn(1295); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1290::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant32(__nt), __end)); - (2, 146) + let __nt = super::__action1295::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant30(__nt), __end)); + (2, 147) } - pub(crate) fn __reduce414< + pub(crate) fn __reduce416< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24871,15 +24945,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument? = FunctionArgument => ActionFn(438); - let __sym0 = __pop_Variant32(__symbols); + // FunctionArgument? = FunctionArgument => ActionFn(443); + let __sym0 = __pop_Variant30(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action438::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant68(__nt), __end)); - (1, 147) + let __nt = super::__action443::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant67(__nt), __end)); + (1, 148) } - pub(crate) fn __reduce415< + pub(crate) fn __reduce417< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24887,14 +24961,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // FunctionArgument? = => ActionFn(439); + // FunctionArgument? = => ActionFn(444); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action439::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant68(__nt), __end)); - (0, 147) + let __nt = super::__action444::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant67(__nt), __end)); + (0, 148) } - pub(crate) fn __reduce416< + pub(crate) fn __reduce418< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24902,17 +24976,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // GenericList = OneOrMore, "," => ActionFn(1291); + // GenericList = OneOrMore, "," => ActionFn(1296); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1291::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 148) + let __nt = super::__action1296::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 149) } - pub(crate) fn __reduce417< + pub(crate) fn __reduce419< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24920,15 +24994,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // GenericList = OneOrMore => ActionFn(1292); - let __sym0 = __pop_Variant34(__symbols); + // GenericList = OneOrMore => ActionFn(1297); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1292::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 148) + let __nt = super::__action1297::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 149) } - pub(crate) fn __reduce418< + pub(crate) fn __reduce420< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24936,17 +25010,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // GenericList = OneOrMore, "," => ActionFn(1293); + // GenericList = OneOrMore, "," => ActionFn(1298); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1293::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 149) + let __nt = super::__action1298::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 150) } - pub(crate) fn __reduce419< + pub(crate) fn __reduce421< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24954,15 +25028,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // GenericList = OneOrMore => ActionFn(1294); - let __sym0 = __pop_Variant34(__symbols); + // GenericList = OneOrMore => ActionFn(1299); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1294::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 149) + let __nt = super::__action1299::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 150) } - pub(crate) fn __reduce420< + pub(crate) fn __reduce422< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24970,17 +25044,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // GlobalStatement = "global", OneOrMore => ActionFn(1295); + // GlobalStatement = "global", OneOrMore => ActionFn(1300); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant78(__symbols); + let __sym1 = __pop_Variant77(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1295::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 150) + let __nt = super::__action1300::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 151) } - pub(crate) fn __reduce421< + pub(crate) fn __reduce423< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -24988,17 +25062,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Guard = "if", NamedExpressionTest => ActionFn(87); + // Guard = "if", NamedExpressionTest => ActionFn(89); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action87::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 151) + let __nt = super::__action89::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 152) } - pub(crate) fn __reduce422< + pub(crate) fn __reduce424< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25006,15 +25080,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Identifier = name => ActionFn(1296); + // Identifier = name => ActionFn(1301); let __sym0 = __pop_Variant5(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1296::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant24(__nt), __end)); - (1, 152) + let __nt = super::__action1301::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant22(__nt), __end)); + (1, 153) } - pub(crate) fn __reduce423< + pub(crate) fn __reduce425< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25022,22 +25096,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // IfStatement = "if", NamedExpressionTest, ":", Suite, "else", ":", Suite => ActionFn(1131); + // IfStatement = "if", NamedExpressionTest, ":", Suite, "else", ":", Suite => ActionFn(1135); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1131::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 153) + let __nt = super::__action1135::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 154) } - pub(crate) fn __reduce424< + pub(crate) fn __reduce426< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25045,19 +25119,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // IfStatement = "if", NamedExpressionTest, ":", Suite => ActionFn(1132); + // IfStatement = "if", NamedExpressionTest, ":", Suite => ActionFn(1136); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1132::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 153) + let __nt = super::__action1136::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 154) } - pub(crate) fn __reduce425< + pub(crate) fn __reduce427< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25065,23 +25139,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // IfStatement = "if", NamedExpressionTest, ":", Suite, (<@L> "elif" ":" )+, "else", ":", Suite => ActionFn(1133); + // IfStatement = "if", NamedExpressionTest, ":", Suite, (<@L> "elif" ":" )+, "else", ":", Suite => ActionFn(1137); assert!(__symbols.len() >= 8); - let __sym7 = __pop_Variant26(__symbols); + let __sym7 = __pop_Variant24(__symbols); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant29(__symbols); - let __sym3 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant27(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action1133::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 153) + let __nt = super::__action1137::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 154) } - pub(crate) fn __reduce426< + pub(crate) fn __reduce428< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25089,20 +25163,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // IfStatement = "if", NamedExpressionTest, ":", Suite, (<@L> "elif" ":" )+ => ActionFn(1134); + // IfStatement = "if", NamedExpressionTest, ":", Suite, (<@L> "elif" ":" )+ => ActionFn(1138); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant29(__symbols); - let __sym3 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant27(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1134::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 153) + let __nt = super::__action1138::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 154) } - pub(crate) fn __reduce427< + pub(crate) fn __reduce429< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25110,18 +25184,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsAlias = DottedName, "as", Identifier => ActionFn(1297); + // ImportAsAlias = DottedName, "as", Identifier => ActionFn(1302); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1297::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant69(__nt), __end)); - (3, 154) + let __nt = super::__action1302::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant68(__nt), __end)); + (3, 155) } - pub(crate) fn __reduce428< + pub(crate) fn __reduce430< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25129,15 +25203,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsAlias = DottedName => ActionFn(1298); - let __sym0 = __pop_Variant24(__symbols); + // ImportAsAlias = DottedName => ActionFn(1303); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1298::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant69(__nt), __end)); - (1, 154) + let __nt = super::__action1303::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant68(__nt), __end)); + (1, 155) } - pub(crate) fn __reduce429< + pub(crate) fn __reduce431< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25145,18 +25219,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsAlias = Identifier, "as", Identifier => ActionFn(1299); + // ImportAsAlias = Identifier, "as", Identifier => ActionFn(1304); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1299::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant69(__nt), __end)); - (3, 155) + let __nt = super::__action1304::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant68(__nt), __end)); + (3, 156) } - pub(crate) fn __reduce430< + pub(crate) fn __reduce432< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25164,15 +25238,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsAlias = Identifier => ActionFn(1300); - let __sym0 = __pop_Variant24(__symbols); + // ImportAsAlias = Identifier => ActionFn(1305); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1300::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant69(__nt), __end)); - (1, 155) + let __nt = super::__action1305::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant68(__nt), __end)); + (1, 156) } - pub(crate) fn __reduce431< + pub(crate) fn __reduce433< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25180,15 +25254,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsNames = OneOrMore> => ActionFn(1301); - let __sym0 = __pop_Variant70(__symbols); + // ImportAsNames = OneOrMore> => ActionFn(1306); + let __sym0 = __pop_Variant69(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1301::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (1, 156) + let __nt = super::__action1306::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (1, 157) } - pub(crate) fn __reduce432< + pub(crate) fn __reduce434< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25196,19 +25270,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsNames = "(", OneOrMore>, ",", ")" => ActionFn(1302); + // ImportAsNames = "(", OneOrMore>, ",", ")" => ActionFn(1307); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant70(__symbols); + let __sym1 = __pop_Variant69(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1302::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (4, 156) + let __nt = super::__action1307::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (4, 157) } - pub(crate) fn __reduce433< + pub(crate) fn __reduce435< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25216,18 +25290,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsNames = "(", OneOrMore>, ")" => ActionFn(1303); + // ImportAsNames = "(", OneOrMore>, ")" => ActionFn(1308); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant70(__symbols); + let __sym1 = __pop_Variant69(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1303::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (3, 156) + let __nt = super::__action1308::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (3, 157) } - pub(crate) fn __reduce434< + pub(crate) fn __reduce436< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25235,15 +25309,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportAsNames = "*" => ActionFn(1304); + // ImportAsNames = "*" => ActionFn(1309); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1304::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (1, 156) + let __nt = super::__action1309::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (1, 157) } - pub(crate) fn __reduce435< + pub(crate) fn __reduce437< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25251,15 +25325,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots = "..." => ActionFn(63); + // ImportDots = "..." => ActionFn(64); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action63::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant71(__nt), __end)); - (1, 157) + let __nt = super::__action64::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant70(__nt), __end)); + (1, 158) } - pub(crate) fn __reduce436< + pub(crate) fn __reduce438< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25267,15 +25341,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots = "." => ActionFn(64); + // ImportDots = "." => ActionFn(65); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action64::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant71(__nt), __end)); - (1, 157) + let __nt = super::__action65::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant70(__nt), __end)); + (1, 158) } - pub(crate) fn __reduce437< + pub(crate) fn __reduce439< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25283,14 +25357,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots* = => ActionFn(364); + // ImportDots* = => ActionFn(369); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action364::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant72(__nt), __end)); - (0, 158) + let __nt = super::__action369::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant71(__nt), __end)); + (0, 159) } - pub(crate) fn __reduce438< + pub(crate) fn __reduce440< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25298,15 +25372,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots* = ImportDots+ => ActionFn(365); - let __sym0 = __pop_Variant72(__symbols); + // ImportDots* = ImportDots+ => ActionFn(370); + let __sym0 = __pop_Variant71(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action365::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant72(__nt), __end)); - (1, 158) + let __nt = super::__action370::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant71(__nt), __end)); + (1, 159) } - pub(crate) fn __reduce439< + pub(crate) fn __reduce441< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25314,15 +25388,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots+ = ImportDots => ActionFn(362); - let __sym0 = __pop_Variant71(__symbols); + // ImportDots+ = ImportDots => ActionFn(367); + let __sym0 = __pop_Variant70(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action362::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant72(__nt), __end)); - (1, 159) + let __nt = super::__action367::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant71(__nt), __end)); + (1, 160) } - pub(crate) fn __reduce440< + pub(crate) fn __reduce442< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25330,17 +25404,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportDots+ = ImportDots+, ImportDots => ActionFn(363); + // ImportDots+ = ImportDots+, ImportDots => ActionFn(368); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant71(__symbols); - let __sym0 = __pop_Variant72(__symbols); + let __sym1 = __pop_Variant70(__symbols); + let __sym0 = __pop_Variant71(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action363::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant72(__nt), __end)); - (2, 159) + let __nt = super::__action368::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant71(__nt), __end)); + (2, 160) } - pub(crate) fn __reduce441< + pub(crate) fn __reduce443< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25348,15 +25422,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportFromLocation = DottedName => ActionFn(1555); - let __sym0 = __pop_Variant24(__symbols); + // ImportFromLocation = DottedName => ActionFn(1562); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1555::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant73(__nt), __end)); - (1, 160) + let __nt = super::__action1562::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant72(__nt), __end)); + (1, 161) } - pub(crate) fn __reduce442< + pub(crate) fn __reduce444< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25364,17 +25438,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportFromLocation = ImportDots+, DottedName => ActionFn(1556); + // ImportFromLocation = ImportDots+, DottedName => ActionFn(1563); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); - let __sym0 = __pop_Variant72(__symbols); + let __sym1 = __pop_Variant22(__symbols); + let __sym0 = __pop_Variant71(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1556::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant73(__nt), __end)); - (2, 160) + let __nt = super::__action1563::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant72(__nt), __end)); + (2, 161) } - pub(crate) fn __reduce443< + pub(crate) fn __reduce445< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25382,15 +25456,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportFromLocation = ImportDots+ => ActionFn(62); - let __sym0 = __pop_Variant72(__symbols); + // ImportFromLocation = ImportDots+ => ActionFn(63); + let __sym0 = __pop_Variant71(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action62::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant73(__nt), __end)); - (1, 160) + let __nt = super::__action63::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant72(__nt), __end)); + (1, 161) } - pub(crate) fn __reduce444< + pub(crate) fn __reduce446< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25398,17 +25472,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportStatement = "import", OneOrMore> => ActionFn(1305); + // ImportStatement = "import", OneOrMore> => ActionFn(1310); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant70(__symbols); + let __sym1 = __pop_Variant69(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1305::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 161) + let __nt = super::__action1310::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 162) } - pub(crate) fn __reduce445< + pub(crate) fn __reduce447< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25416,19 +25490,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ImportStatement = "from", ImportFromLocation, "import", ImportAsNames => ActionFn(1306); + // ImportStatement = "from", ImportFromLocation, "import", ImportAsNames => ActionFn(1311); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant70(__symbols); + let __sym3 = __pop_Variant69(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant73(__symbols); + let __sym1 = __pop_Variant72(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1306::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 161) + let __nt = super::__action1311::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 162) } - pub(crate) fn __reduce446< + pub(crate) fn __reduce451< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25436,17 +25510,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // KwargParameter = "**", DoubleStarTypedParameter => ActionFn(1545); + // KwargParameter = "**", DoubleStarTypedParameter => ActionFn(1552); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1545::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant10(__nt), __end)); - (2, 162) + let __nt = super::__action1552::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (2, 166) } - pub(crate) fn __reduce447< + pub(crate) fn __reduce452< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25454,15 +25528,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // KwargParameter = "**" => ActionFn(1546); + // KwargParameter = "**" => ActionFn(1553); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1546::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant10(__nt), __end)); - (1, 162) + let __nt = super::__action1553::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (1, 166) } - pub(crate) fn __reduce448< + pub(crate) fn __reduce453< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25470,17 +25544,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // KwargParameter = "**", StarUntypedParameter => ActionFn(997); + // KwargParameter = "**", StarUntypedParameter => ActionFn(999); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant64(__symbols); + let __sym1 = __pop_Variant63(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action997::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant10(__nt), __end)); - (2, 163) + let __nt = super::__action999::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (2, 167) } - pub(crate) fn __reduce449< + pub(crate) fn __reduce454< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25488,15 +25562,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // KwargParameter = "**" => ActionFn(998); + // KwargParameter = "**" => ActionFn(1000); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action998::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant10(__nt), __end)); - (1, 163) + let __nt = super::__action1000::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (1, 167) } - pub(crate) fn __reduce454< + pub(crate) fn __reduce457< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25504,17 +25578,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ListLiteralValues = OneOrMore, "," => ActionFn(608); + // ListLiteralValues = OneOrMore, "," => ActionFn(613); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action608::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (2, 167) + let __nt = super::__action613::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (2, 169) } - pub(crate) fn __reduce455< + pub(crate) fn __reduce458< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25522,15 +25596,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ListLiteralValues = OneOrMore => ActionFn(609); - let __sym0 = __pop_Variant34(__symbols); + // ListLiteralValues = OneOrMore => ActionFn(614); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action609::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 167) + let __nt = super::__action614::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 169) } - pub(crate) fn __reduce456< + pub(crate) fn __reduce459< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25538,15 +25612,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ListLiteralValues? = ListLiteralValues => ActionFn(548); - let __sym0 = __pop_Variant34(__symbols); + // ListLiteralValues? = ListLiteralValues => ActionFn(551); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action548::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant35(__nt), __end)); - (1, 168) + let __nt = super::__action551::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + (1, 170) } - pub(crate) fn __reduce457< + pub(crate) fn __reduce460< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25554,14 +25628,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ListLiteralValues? = => ActionFn(549); + // ListLiteralValues? = => ActionFn(552); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action549::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant35(__nt), __end)); - (0, 168) + let __nt = super::__action552::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant33(__nt), __end)); + (0, 170) } - pub(crate) fn __reduce458< + pub(crate) fn __reduce461< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25569,15 +25643,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // LiteralPattern = "None" => ActionFn(1310); + // LiteralPattern = "None" => ActionFn(1316); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1310::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + let __nt = super::__action1316::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } - pub(crate) fn __reduce459< + pub(crate) fn __reduce462< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25585,15 +25659,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // LiteralPattern = "True" => ActionFn(1311); + // LiteralPattern = "True" => ActionFn(1317); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1311::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + let __nt = super::__action1317::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } - pub(crate) fn __reduce460< + pub(crate) fn __reduce463< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25601,15 +25675,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // LiteralPattern = "False" => ActionFn(1312); + // LiteralPattern = "False" => ActionFn(1318); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1312::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + let __nt = super::__action1318::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } - pub(crate) fn __reduce461< + pub(crate) fn __reduce464< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25617,15 +25691,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // LiteralPattern = ConstantExpr => ActionFn(1313); - let __sym0 = __pop_Variant16(__symbols); + // LiteralPattern = ConstantExpr => ActionFn(1319); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1313::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + let __nt = super::__action1319::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } - pub(crate) fn __reduce462< + pub(crate) fn __reduce465< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25633,15 +25707,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // LiteralPattern = AddOpExpr => ActionFn(1314); - let __sym0 = __pop_Variant16(__symbols); + // LiteralPattern = AddOpExpr => ActionFn(1320); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1314::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 169) + let __nt = super::__action1320::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 171) } - pub(crate) fn __reduce464< + pub(crate) fn __reduce467< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25649,15 +25723,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = ConstantExpr => ActionFn(124); - let __sym0 = __pop_Variant16(__symbols); + // MappingKey = ConstantExpr => ActionFn(126); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action124::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action126::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce465< + pub(crate) fn __reduce468< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25665,15 +25739,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = AddOpExpr => ActionFn(125); - let __sym0 = __pop_Variant16(__symbols); + // MappingKey = AddOpExpr => ActionFn(127); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action125::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action127::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce466< + pub(crate) fn __reduce469< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25681,15 +25755,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = MatchNameOrAttr => ActionFn(126); - let __sym0 = __pop_Variant16(__symbols); + // MappingKey = MatchNameOrAttr => ActionFn(128); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action126::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action128::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce467< + pub(crate) fn __reduce470< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25697,15 +25771,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = "None" => ActionFn(1316); + // MappingKey = "None" => ActionFn(1322); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1316::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action1322::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce468< + pub(crate) fn __reduce471< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25713,15 +25787,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = "True" => ActionFn(1317); + // MappingKey = "True" => ActionFn(1323); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1317::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action1323::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce469< + pub(crate) fn __reduce472< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25729,15 +25803,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingKey = "False" => ActionFn(1318); + // MappingKey = "False" => ActionFn(1324); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1318::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 170) + let __nt = super::__action1324::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 172) } - pub(crate) fn __reduce471< + pub(crate) fn __reduce474< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25745,17 +25819,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", "}" => ActionFn(1319); + // MappingPattern = "{", "}" => ActionFn(1325); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1319::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 171) + let __nt = super::__action1325::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 173) } - pub(crate) fn __reduce472< + pub(crate) fn __reduce475< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25763,19 +25837,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", OneOrMore, ",", "}" => ActionFn(1320); + // MappingPattern = "{", OneOrMore, ",", "}" => ActionFn(1326); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant80(__symbols); + let __sym1 = __pop_Variant79(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1320::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 171) + let __nt = super::__action1326::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 173) } - pub(crate) fn __reduce473< + pub(crate) fn __reduce476< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25783,18 +25857,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", OneOrMore, "}" => ActionFn(1321); + // MappingPattern = "{", OneOrMore, "}" => ActionFn(1327); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant80(__symbols); + let __sym1 = __pop_Variant79(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1321::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 171) + let __nt = super::__action1327::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 173) } - pub(crate) fn __reduce474< + pub(crate) fn __reduce477< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25802,20 +25876,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", "**", Identifier, ",", "}" => ActionFn(1322); + // MappingPattern = "{", "**", Identifier, ",", "}" => ActionFn(1328); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1322::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 171) + let __nt = super::__action1328::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 173) } - pub(crate) fn __reduce475< + pub(crate) fn __reduce478< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25823,19 +25897,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", "**", Identifier, "}" => ActionFn(1323); + // MappingPattern = "{", "**", Identifier, "}" => ActionFn(1329); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1323::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 171) + let __nt = super::__action1329::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 173) } - pub(crate) fn __reduce476< + pub(crate) fn __reduce479< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25843,22 +25917,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", OneOrMore, ",", "**", Identifier, ",", "}" => ActionFn(1324); + // MappingPattern = "{", OneOrMore, ",", "**", Identifier, ",", "}" => ActionFn(1330); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant22(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant80(__symbols); + let __sym1 = __pop_Variant79(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1324::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (7, 171) + let __nt = super::__action1330::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (7, 173) } - pub(crate) fn __reduce477< + pub(crate) fn __reduce480< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25866,21 +25940,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MappingPattern = "{", OneOrMore, ",", "**", Identifier, "}" => ActionFn(1325); + // MappingPattern = "{", OneOrMore, ",", "**", Identifier, "}" => ActionFn(1331); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant22(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant80(__symbols); + let __sym1 = __pop_Variant79(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1325::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (6, 171) + let __nt = super::__action1331::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (6, 173) } - pub(crate) fn __reduce478< + pub(crate) fn __reduce481< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25888,20 +25962,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchCase = "case", Patterns, Guard, ":", Suite => ActionFn(1498); + // MatchCase = "case", Patterns, Guard, ":", Suite => ActionFn(1503); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant34(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1498::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant74(__nt), __end)); - (5, 172) + let __nt = super::__action1503::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant73(__nt), __end)); + (5, 174) } - pub(crate) fn __reduce479< + pub(crate) fn __reduce482< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25909,19 +25983,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchCase = "case", Patterns, ":", Suite => ActionFn(1499); + // MatchCase = "case", Patterns, ":", Suite => ActionFn(1504); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant34(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1499::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant74(__nt), __end)); - (4, 172) + let __nt = super::__action1504::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant73(__nt), __end)); + (4, 174) } - pub(crate) fn __reduce480< + pub(crate) fn __reduce483< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25930,14 +26004,14 @@ mod __parse__Top { ) -> (usize, usize) { // MatchCase+ = MatchCase => ActionFn(347); - let __sym0 = __pop_Variant74(__symbols); + let __sym0 = __pop_Variant73(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action347::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant75(__nt), __end)); - (1, 173) + __symbols.push((__start, __Symbol::Variant74(__nt), __end)); + (1, 175) } - pub(crate) fn __reduce481< + pub(crate) fn __reduce484< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25947,15 +26021,15 @@ mod __parse__Top { { // MatchCase+ = MatchCase+, MatchCase => ActionFn(348); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant74(__symbols); - let __sym0 = __pop_Variant75(__symbols); + let __sym1 = __pop_Variant73(__symbols); + let __sym0 = __pop_Variant74(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action348::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant75(__nt), __end)); - (2, 173) + __symbols.push((__start, __Symbol::Variant74(__nt), __end)); + (2, 175) } - pub(crate) fn __reduce482< + pub(crate) fn __reduce485< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25963,18 +26037,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchKeywordEntry = Identifier, "=", Pattern => ActionFn(136); + // MatchKeywordEntry = Identifier, "=", Pattern => ActionFn(138); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action136::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant76(__nt), __end)); - (3, 174) + let __nt = super::__action138::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant75(__nt), __end)); + (3, 176) } - pub(crate) fn __reduce483< + pub(crate) fn __reduce486< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -25982,18 +26056,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchMappingEntry = MappingKey, ":", Pattern => ActionFn(131); + // MatchMappingEntry = MappingKey, ":", Pattern => ActionFn(133); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action131::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant77(__nt), __end)); - (3, 175) + let __nt = super::__action133::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant76(__nt), __end)); + (3, 177) } - pub(crate) fn __reduce484< + pub(crate) fn __reduce487< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26001,15 +26075,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchName = Identifier => ActionFn(1326); - let __sym0 = __pop_Variant24(__symbols); + // MatchName = Identifier => ActionFn(1332); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1326::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 176) + let __nt = super::__action1332::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 178) } - pub(crate) fn __reduce485< + pub(crate) fn __reduce488< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26017,18 +26091,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchNameOrAttr = MatchName, ".", Identifier => ActionFn(1327); + // MatchNameOrAttr = MatchName, ".", Identifier => ActionFn(1333); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1327::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 177) + let __nt = super::__action1333::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 179) } - pub(crate) fn __reduce486< + pub(crate) fn __reduce489< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26036,18 +26110,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchNameOrAttr = MatchNameOrAttr, ".", Identifier => ActionFn(1328); + // MatchNameOrAttr = MatchNameOrAttr, ".", Identifier => ActionFn(1334); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1328::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 177) + let __nt = super::__action1334::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 179) } - pub(crate) fn __reduce487< + pub(crate) fn __reduce490< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26055,22 +26129,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchStatement = "match", TestOrStarNamedExpr, ":", "\n", Indent, MatchCase+, Dedent => ActionFn(847); + // MatchStatement = "match", TestOrStarNamedExpr, ":", "\n", Indent, MatchCase+, Dedent => ActionFn(850); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant75(__symbols); + let __sym5 = __pop_Variant74(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action847::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 178) + let __nt = super::__action850::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 180) } - pub(crate) fn __reduce488< + pub(crate) fn __reduce491< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26078,23 +26152,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchStatement = "match", TestOrStarNamedExpr, ",", ":", "\n", Indent, MatchCase+, Dedent => ActionFn(848); + // MatchStatement = "match", TestOrStarNamedExpr, ",", ":", "\n", Indent, MatchCase+, Dedent => ActionFn(851); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant75(__symbols); + let __sym6 = __pop_Variant74(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action848::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 178) + let __nt = super::__action851::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 180) } - pub(crate) fn __reduce489< + pub(crate) fn __reduce492< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26102,23 +26176,23 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchStatement = "match", TwoOrMore, ",", ":", "\n", Indent, MatchCase+, Dedent => ActionFn(849); + // MatchStatement = "match", TwoOrMore, ",", ":", "\n", Indent, MatchCase+, Dedent => ActionFn(852); assert!(__symbols.len() >= 8); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant75(__symbols); + let __sym6 = __pop_Variant74(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym7.2; - let __nt = super::__action849::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (8, 178) + let __nt = super::__action852::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (8, 180) } - pub(crate) fn __reduce490< + pub(crate) fn __reduce493< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26126,22 +26200,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MatchStatement = "match", TwoOrMore, ":", "\n", Indent, MatchCase+, Dedent => ActionFn(850); + // MatchStatement = "match", TwoOrMore, ":", "\n", Indent, MatchCase+, Dedent => ActionFn(853); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); - let __sym5 = __pop_Variant75(__symbols); + let __sym5 = __pop_Variant74(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action850::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 178) + let __nt = super::__action853::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 180) } - pub(crate) fn __reduce491< + pub(crate) fn __reduce494< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26149,15 +26223,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MulOp = "*" => ActionFn(196); + // MulOp = "*" => ActionFn(200); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action196::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 179) + let __nt = super::__action200::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 181) } - pub(crate) fn __reduce492< + pub(crate) fn __reduce495< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26165,15 +26239,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MulOp = "/" => ActionFn(197); + // MulOp = "/" => ActionFn(201); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action197::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 179) + let __nt = super::__action201::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 181) } - pub(crate) fn __reduce493< + pub(crate) fn __reduce496< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26181,15 +26255,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MulOp = "//" => ActionFn(198); + // MulOp = "//" => ActionFn(202); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action198::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 179) + let __nt = super::__action202::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 181) } - pub(crate) fn __reduce494< + pub(crate) fn __reduce497< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26197,15 +26271,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MulOp = "%" => ActionFn(199); + // MulOp = "%" => ActionFn(203); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action199::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 179) + let __nt = super::__action203::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 181) } - pub(crate) fn __reduce495< + pub(crate) fn __reduce498< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26213,15 +26287,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // MulOp = "@" => ActionFn(200); + // MulOp = "@" => ActionFn(204); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action200::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 179) + let __nt = super::__action204::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 181) } - pub(crate) fn __reduce496< + pub(crate) fn __reduce499< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26229,18 +26303,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NamedExpression = Identifier, ":=", Test<"all"> => ActionFn(1329); + // NamedExpression = NamedExpressionName, ":=", Test<"all"> => ActionFn(1335); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1329::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 180) + let __nt = super::__action1335::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 182) } - pub(crate) fn __reduce497< + pub(crate) fn __reduce500< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26248,15 +26322,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NamedExpressionTest = NamedExpression => ActionFn(178); - let __sym0 = __pop_Variant16(__symbols); + // NamedExpressionName = Identifier => ActionFn(1336); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action178::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 181) + let __nt = super::__action1336::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 183) } - pub(crate) fn __reduce498< + pub(crate) fn __reduce501< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26264,15 +26338,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NamedExpressionTest = Test<"all"> => ActionFn(179); - let __sym0 = __pop_Variant16(__symbols); + // NamedExpressionTest = NamedExpression => ActionFn(181); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action179::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 181) + let __nt = super::__action181::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 184) } - pub(crate) fn __reduce499< + pub(crate) fn __reduce502< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26280,15 +26354,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NamedOrStarExpr = NamedExpression => ActionFn(35); - let __sym0 = __pop_Variant16(__symbols); + // NamedExpressionTest = Test<"all"> => ActionFn(182); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action35::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 182) + let __nt = super::__action182::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 184) } - pub(crate) fn __reduce500< + pub(crate) fn __reduce503< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26296,15 +26370,31 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NamedOrStarExpr = StarExpr => ActionFn(36); - let __sym0 = __pop_Variant16(__symbols); + // NamedOrStarExpr = NamedExpression => ActionFn(36); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action36::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 182) + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 185) } - pub(crate) fn __reduce501< + pub(crate) fn __reduce504< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // NamedOrStarExpr = StarExpr => ActionFn(37); + let __sym0 = __pop_Variant14(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action37::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 185) + } + pub(crate) fn __reduce505< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26312,17 +26402,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NonlocalStatement = "nonlocal", OneOrMore => ActionFn(1330); + // NonlocalStatement = "nonlocal", OneOrMore => ActionFn(1337); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant78(__symbols); + let __sym1 = __pop_Variant77(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1330::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 183) + let __nt = super::__action1337::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 186) } - pub(crate) fn __reduce502< + pub(crate) fn __reduce506< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26330,17 +26420,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NotTest<"all"> = "not", NotTest<"all"> => ActionFn(1331); + // NotTest<"all"> = "not", NotTest<"all"> => ActionFn(1338); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1331::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 184) + let __nt = super::__action1338::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 187) } - pub(crate) fn __reduce503< + pub(crate) fn __reduce507< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26348,15 +26438,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NotTest<"all"> = Comparison<"all"> => ActionFn(449); - let __sym0 = __pop_Variant16(__symbols); + // NotTest<"all"> = Comparison<"all"> => ActionFn(454); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action449::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 184) + let __nt = super::__action454::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 187) } - pub(crate) fn __reduce504< + pub(crate) fn __reduce508< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26364,17 +26454,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NotTest<"no-withitems"> = "not", NotTest<"all"> => ActionFn(1332); + // NotTest<"no-withitems"> = "not", NotTest<"all"> => ActionFn(1339); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1332::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 185) + let __nt = super::__action1339::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 188) } - pub(crate) fn __reduce505< + pub(crate) fn __reduce509< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26382,15 +26472,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // NotTest<"no-withitems"> = Comparison<"no-withitems"> => ActionFn(494); - let __sym0 = __pop_Variant16(__symbols); + // NotTest<"no-withitems"> = Comparison<"no-withitems"> => ActionFn(497); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action494::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 185) + let __nt = super::__action497::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 188) } - pub(crate) fn __reduce506< + pub(crate) fn __reduce510< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26398,15 +26488,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = DictElement => ActionFn(250); - let __sym0 = __pop_Variant60(__symbols); + // OneOrMore = DictElement => ActionFn(252); + let __sym0 = __pop_Variant59(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action250::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant62(__nt), __end)); - (1, 186) + let __nt = super::__action252::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant61(__nt), __end)); + (1, 189) } - pub(crate) fn __reduce507< + pub(crate) fn __reduce511< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26414,18 +26504,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", DictElement => ActionFn(251); + // OneOrMore = OneOrMore, ",", DictElement => ActionFn(253); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant60(__symbols); + let __sym2 = __pop_Variant59(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant62(__symbols); + let __sym0 = __pop_Variant61(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action251::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant62(__nt), __end)); - (3, 186) + let __nt = super::__action253::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant61(__nt), __end)); + (3, 189) } - pub(crate) fn __reduce508< + pub(crate) fn __reduce512< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26433,15 +26523,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = ExpressionOrStarExpression => ActionFn(245); - let __sym0 = __pop_Variant16(__symbols); + // OneOrMore = ExpressionOrStarExpression => ActionFn(249); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action245::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 187) + let __nt = super::__action249::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 190) } - pub(crate) fn __reduce509< + pub(crate) fn __reduce513< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26449,18 +26539,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", ExpressionOrStarExpression => ActionFn(246); + // OneOrMore = OneOrMore, ",", ExpressionOrStarExpression => ActionFn(250); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action246::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 187) + let __nt = super::__action250::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 190) } - pub(crate) fn __reduce510< + pub(crate) fn __reduce514< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26468,15 +26558,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = Identifier => ActionFn(352); - let __sym0 = __pop_Variant24(__symbols); + // OneOrMore = Identifier => ActionFn(357); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action352::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant78(__nt), __end)); - (1, 188) + let __nt = super::__action357::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant77(__nt), __end)); + (1, 191) } - pub(crate) fn __reduce511< + pub(crate) fn __reduce515< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26484,18 +26574,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", Identifier => ActionFn(353); + // OneOrMore = OneOrMore, ",", Identifier => ActionFn(358); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant78(__symbols); + let __sym0 = __pop_Variant77(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action353::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant78(__nt), __end)); - (3, 188) + let __nt = super::__action358::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant77(__nt), __end)); + (3, 191) } - pub(crate) fn __reduce512< + pub(crate) fn __reduce516< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26503,18 +26593,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = DottedName, "as", Identifier => ActionFn(1547); + // OneOrMore> = DottedName, "as", Identifier => ActionFn(1554); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1547::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (3, 189) + let __nt = super::__action1554::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (3, 192) } - pub(crate) fn __reduce513< + pub(crate) fn __reduce517< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26522,15 +26612,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = DottedName => ActionFn(1548); - let __sym0 = __pop_Variant24(__symbols); + // OneOrMore> = DottedName => ActionFn(1555); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1548::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (1, 189) + let __nt = super::__action1555::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (1, 192) } - pub(crate) fn __reduce514< + pub(crate) fn __reduce518< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26538,20 +26628,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", DottedName, "as", Identifier => ActionFn(1549); + // OneOrMore> = OneOrMore>, ",", DottedName, "as", Identifier => ActionFn(1556); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant22(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant70(__symbols); + let __sym0 = __pop_Variant69(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1549::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (5, 189) + let __nt = super::__action1556::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (5, 192) } - pub(crate) fn __reduce515< + pub(crate) fn __reduce519< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26559,18 +26649,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", DottedName => ActionFn(1550); + // OneOrMore> = OneOrMore>, ",", DottedName => ActionFn(1557); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant70(__symbols); + let __sym0 = __pop_Variant69(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1550::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (3, 189) + let __nt = super::__action1557::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (3, 192) } - pub(crate) fn __reduce516< + pub(crate) fn __reduce520< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26578,18 +26668,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = Identifier, "as", Identifier => ActionFn(1551); + // OneOrMore> = Identifier, "as", Identifier => ActionFn(1558); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1551::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (3, 190) + let __nt = super::__action1558::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (3, 193) } - pub(crate) fn __reduce517< + pub(crate) fn __reduce521< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26597,15 +26687,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = Identifier => ActionFn(1552); - let __sym0 = __pop_Variant24(__symbols); + // OneOrMore> = Identifier => ActionFn(1559); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1552::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (1, 190) + let __nt = super::__action1559::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (1, 193) } - pub(crate) fn __reduce518< + pub(crate) fn __reduce522< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26613,20 +26703,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", Identifier, "as", Identifier => ActionFn(1553); + // OneOrMore> = OneOrMore>, ",", Identifier, "as", Identifier => ActionFn(1560); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant24(__symbols); + let __sym4 = __pop_Variant22(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant70(__symbols); + let __sym0 = __pop_Variant69(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1553::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (5, 190) + let __nt = super::__action1560::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (5, 193) } - pub(crate) fn __reduce519< + pub(crate) fn __reduce523< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26634,18 +26724,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", Identifier => ActionFn(1554); + // OneOrMore> = OneOrMore>, ",", Identifier => ActionFn(1561); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant24(__symbols); + let __sym2 = __pop_Variant22(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant70(__symbols); + let __sym0 = __pop_Variant69(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1554::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant70(__nt), __end)); - (3, 190) + let __nt = super::__action1561::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant69(__nt), __end)); + (3, 193) } - pub(crate) fn __reduce520< + pub(crate) fn __reduce524< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26654,14 +26744,14 @@ mod __parse__Top { ) -> (usize, usize) { // OneOrMore = MatchKeywordEntry => ActionFn(325); - let __sym0 = __pop_Variant76(__symbols); + let __sym0 = __pop_Variant75(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action325::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant79(__nt), __end)); - (1, 191) + __symbols.push((__start, __Symbol::Variant78(__nt), __end)); + (1, 194) } - pub(crate) fn __reduce521< + pub(crate) fn __reduce525< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26671,16 +26761,16 @@ mod __parse__Top { { // OneOrMore = OneOrMore, ",", MatchKeywordEntry => ActionFn(326); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant76(__symbols); + let __sym2 = __pop_Variant75(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant79(__symbols); + let __sym0 = __pop_Variant78(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action326::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant79(__nt), __end)); - (3, 191) + __symbols.push((__start, __Symbol::Variant78(__nt), __end)); + (3, 194) } - pub(crate) fn __reduce522< + pub(crate) fn __reduce526< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26689,14 +26779,14 @@ mod __parse__Top { ) -> (usize, usize) { // OneOrMore = MatchMappingEntry => ActionFn(329); - let __sym0 = __pop_Variant77(__symbols); + let __sym0 = __pop_Variant76(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action329::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant80(__nt), __end)); - (1, 192) + __symbols.push((__start, __Symbol::Variant79(__nt), __end)); + (1, 195) } - pub(crate) fn __reduce523< + pub(crate) fn __reduce527< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26706,16 +26796,16 @@ mod __parse__Top { { // OneOrMore = OneOrMore, ",", MatchMappingEntry => ActionFn(330); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant77(__symbols); + let __sym2 = __pop_Variant76(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant80(__symbols); + let __sym0 = __pop_Variant79(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action330::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant80(__nt), __end)); - (3, 192) + __symbols.push((__start, __Symbol::Variant79(__nt), __end)); + (3, 195) } - pub(crate) fn __reduce524< + pub(crate) fn __reduce528< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26723,15 +26813,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = ParameterDef => ActionFn(463); - let __sym0 = __pop_Variant12(__symbols); + // OneOrMore> = ParameterDef => ActionFn(466); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action463::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant81(__nt), __end)); - (1, 193) + let __nt = super::__action466::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant80(__nt), __end)); + (1, 196) } - pub(crate) fn __reduce525< + pub(crate) fn __reduce529< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26739,18 +26829,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", ParameterDef => ActionFn(464); + // OneOrMore> = OneOrMore>, ",", ParameterDef => ActionFn(467); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant12(__symbols); + let __sym2 = __pop_Variant10(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action464::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant81(__nt), __end)); - (3, 193) + let __nt = super::__action467::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant80(__nt), __end)); + (3, 196) } - pub(crate) fn __reduce526< + pub(crate) fn __reduce530< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26758,15 +26848,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = ParameterDef => ActionFn(452); - let __sym0 = __pop_Variant12(__symbols); + // OneOrMore> = ParameterDef => ActionFn(455); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action452::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant81(__nt), __end)); - (1, 194) + let __nt = super::__action455::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant80(__nt), __end)); + (1, 197) } - pub(crate) fn __reduce527< + pub(crate) fn __reduce531< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26774,18 +26864,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", ParameterDef => ActionFn(453); + // OneOrMore> = OneOrMore>, ",", ParameterDef => ActionFn(456); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant12(__symbols); + let __sym2 = __pop_Variant10(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action453::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant81(__nt), __end)); - (3, 194) + let __nt = super::__action456::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant80(__nt), __end)); + (3, 197) } - pub(crate) fn __reduce528< + pub(crate) fn __reduce532< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26794,14 +26884,14 @@ mod __parse__Top { ) -> (usize, usize) { // OneOrMore = Pattern => ActionFn(327); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action327::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (1, 195) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (1, 198) } - pub(crate) fn __reduce529< + pub(crate) fn __reduce533< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26811,16 +26901,16 @@ mod __parse__Top { { // OneOrMore = OneOrMore, ",", Pattern => ActionFn(328); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant53(__symbols); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action328::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (3, 195) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (3, 198) } - pub(crate) fn __reduce530< + pub(crate) fn __reduce534< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26828,15 +26918,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = Test<"all"> => ActionFn(289); - let __sym0 = __pop_Variant16(__symbols); + // OneOrMore> = Test<"all"> => ActionFn(290); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action289::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 196) + let __nt = super::__action290::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 199) } - pub(crate) fn __reduce531< + pub(crate) fn __reduce535< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26844,18 +26934,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore> = OneOrMore>, ",", Test<"all"> => ActionFn(290); + // OneOrMore> = OneOrMore>, ",", Test<"all"> => ActionFn(291); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action290::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 196) + let __nt = super::__action291::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 199) } - pub(crate) fn __reduce532< + pub(crate) fn __reduce536< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26863,15 +26953,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = TestOrStarExpr => ActionFn(429); - let __sym0 = __pop_Variant16(__symbols); + // OneOrMore = TestOrStarExpr => ActionFn(434); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action429::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 197) + let __nt = super::__action434::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 200) } - pub(crate) fn __reduce533< + pub(crate) fn __reduce537< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26879,18 +26969,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", TestOrStarExpr => ActionFn(430); + // OneOrMore = OneOrMore, ",", TestOrStarExpr => ActionFn(435); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action430::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 197) + let __nt = super::__action435::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 200) } - pub(crate) fn __reduce534< + pub(crate) fn __reduce538< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26898,15 +26988,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = TestOrStarNamedExpr => ActionFn(252); - let __sym0 = __pop_Variant16(__symbols); + // OneOrMore = TestOrStarNamedExpr => ActionFn(254); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action252::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 198) + let __nt = super::__action254::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 201) } - pub(crate) fn __reduce535< + pub(crate) fn __reduce539< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26914,18 +27004,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", TestOrStarNamedExpr => ActionFn(253); + // OneOrMore = OneOrMore, ",", TestOrStarNamedExpr => ActionFn(255); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action253::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 198) + let __nt = super::__action255::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 201) } - pub(crate) fn __reduce536< + pub(crate) fn __reduce540< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26933,15 +27023,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = TypeParam => ActionFn(264); - let __sym0 = __pop_Variant91(__symbols); + // OneOrMore = TypeParam => ActionFn(266); + let __sym0 = __pop_Variant90(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action264::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant82(__nt), __end)); - (1, 199) + let __nt = super::__action266::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant81(__nt), __end)); + (1, 202) } - pub(crate) fn __reduce537< + pub(crate) fn __reduce541< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26949,18 +27039,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OneOrMore = OneOrMore, ",", TypeParam => ActionFn(265); + // OneOrMore = OneOrMore, ",", TypeParam => ActionFn(267); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant91(__symbols); + let __sym2 = __pop_Variant90(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant82(__symbols); + let __sym0 = __pop_Variant81(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action265::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant82(__nt), __end)); - (3, 199) + let __nt = super::__action267::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant81(__nt), __end)); + (3, 202) } - pub(crate) fn __reduce538< + pub(crate) fn __reduce542< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26968,15 +27058,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrPattern = ClosedPattern => ActionFn(94); - let __sym0 = __pop_Variant36(__symbols); + // OrPattern = ClosedPattern => ActionFn(96); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action94::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 200) + let __nt = super::__action96::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 203) } - pub(crate) fn __reduce539< + pub(crate) fn __reduce543< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -26984,15 +27074,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrPattern = TwoOrMore => ActionFn(1333); - let __sym0 = __pop_Variant53(__symbols); + // OrPattern = TwoOrMore => ActionFn(1340); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1333::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 200) + let __nt = super::__action1340::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 203) } - pub(crate) fn __reduce540< + pub(crate) fn __reduce544< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27000,17 +27090,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrTest<"all"> = (> "or")+, AndTest<"all"> => ActionFn(1334); + // OrTest<"all"> = (> "or")+, AndTest<"all"> => ActionFn(1341); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1334::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 201) + let __nt = super::__action1341::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 204) } - pub(crate) fn __reduce541< + pub(crate) fn __reduce545< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27018,15 +27108,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrTest<"all"> = AndTest<"all"> => ActionFn(241); - let __sym0 = __pop_Variant16(__symbols); + // OrTest<"all"> = AndTest<"all"> => ActionFn(245); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action241::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 201) + let __nt = super::__action245::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 204) } - pub(crate) fn __reduce542< + pub(crate) fn __reduce546< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27034,17 +27124,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrTest<"no-withitems"> = (> "or")+, AndTest<"all"> => ActionFn(1335); + // OrTest<"no-withitems"> = (> "or")+, AndTest<"all"> => ActionFn(1342); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); - let __sym0 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant14(__symbols); + let __sym0 = __pop_Variant16(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1335::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 202) + let __nt = super::__action1342::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 205) } - pub(crate) fn __reduce543< + pub(crate) fn __reduce547< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27052,15 +27142,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // OrTest<"no-withitems"> = AndTest<"no-withitems"> => ActionFn(477); - let __sym0 = __pop_Variant16(__symbols); + // OrTest<"no-withitems"> = AndTest<"no-withitems"> => ActionFn(480); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action477::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 202) + let __nt = super::__action480::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 205) } - pub(crate) fn __reduce544< + pub(crate) fn __reduce548< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27068,15 +27158,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDef = TypedParameter => ActionFn(470); - let __sym0 = __pop_Variant12(__symbols); + // ParameterDef = TypedParameter => ActionFn(473); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action470::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (1, 203) + let __nt = super::__action473::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (1, 206) } - pub(crate) fn __reduce545< + pub(crate) fn __reduce549< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27084,18 +27174,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDef = TypedParameter, "=", Test<"all"> => ActionFn(1336); + // ParameterDef = TypedParameter, "=", Test<"all"> => ActionFn(1343); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant12(__symbols); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1336::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (3, 203) + let __nt = super::__action1343::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (3, 206) } - pub(crate) fn __reduce546< + pub(crate) fn __reduce550< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27103,15 +27193,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDef = UntypedParameter => ActionFn(459); - let __sym0 = __pop_Variant12(__symbols); + // ParameterDef = UntypedParameter => ActionFn(462); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action459::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (1, 204) + let __nt = super::__action462::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (1, 207) } - pub(crate) fn __reduce547< + pub(crate) fn __reduce551< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27119,18 +27209,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDef = UntypedParameter, "=", Test<"all"> => ActionFn(1337); + // ParameterDef = UntypedParameter, "=", Test<"all"> => ActionFn(1344); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant12(__symbols); + let __sym0 = __pop_Variant10(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1337::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (3, 204) + let __nt = super::__action1344::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (3, 207) } - pub(crate) fn __reduce548< + pub(crate) fn __reduce552< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27138,15 +27228,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore> => ActionFn(417); - let __sym0 = __pop_Variant81(__symbols); + // ParameterDefs = OneOrMore> => ActionFn(424); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action417::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (1, 205) + let __nt = super::__action424::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (1, 208) } - pub(crate) fn __reduce549< + pub(crate) fn __reduce553< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27154,18 +27244,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore>, ",", "/" => ActionFn(679); + // ParameterDefs = OneOrMore>, ",", "/" => ActionFn(681); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action679::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (3, 205) + let __nt = super::__action681::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (3, 208) } - pub(crate) fn __reduce550< + pub(crate) fn __reduce554< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27173,19 +27263,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore>, ",", "/", ("," >)+ => ActionFn(680); + // ParameterDefs = OneOrMore>, ",", "/", ("," >)+ => ActionFn(682); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action680::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (4, 205) + let __nt = super::__action682::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (4, 208) } - pub(crate) fn __reduce551< + pub(crate) fn __reduce555< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27193,15 +27283,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore> => ActionFn(425); - let __sym0 = __pop_Variant81(__symbols); + // ParameterDefs = OneOrMore> => ActionFn(432); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action425::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (1, 206) + let __nt = super::__action432::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (1, 209) } - pub(crate) fn __reduce552< + pub(crate) fn __reduce556< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27209,18 +27299,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore>, ",", "/" => ActionFn(687); + // ParameterDefs = OneOrMore>, ",", "/" => ActionFn(689); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action687::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (3, 206) + let __nt = super::__action689::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (3, 209) } - pub(crate) fn __reduce553< + pub(crate) fn __reduce557< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27228,19 +27318,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterDefs = OneOrMore>, ",", "/", ("," >)+ => ActionFn(688); + // ParameterDefs = OneOrMore>, ",", "/", ("," >)+ => ActionFn(690); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant13(__symbols); + let __sym3 = __pop_Variant11(__symbols); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant81(__symbols); + let __sym0 = __pop_Variant80(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action688::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant83(__nt), __end)); - (4, 206) + let __nt = super::__action690::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant82(__nt), __end)); + (4, 209) } - pub(crate) fn __reduce630< + pub(crate) fn __reduce634< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27248,17 +27338,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList = KwargParameter, "," => ActionFn(1374); + // ParameterList = KwargParameter, "," => ActionFn(1381); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant10(__symbols); + let __sym0 = __pop_Variant8(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1374::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 207) + let __nt = super::__action1381::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 210) } - pub(crate) fn __reduce631< + pub(crate) fn __reduce635< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27266,15 +27356,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList = KwargParameter => ActionFn(1375); - let __sym0 = __pop_Variant10(__symbols); + // ParameterList = KwargParameter => ActionFn(1382); + let __sym0 = __pop_Variant8(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1375::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 207) + let __nt = super::__action1382::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 210) } - pub(crate) fn __reduce708< + pub(crate) fn __reduce712< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27282,17 +27372,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList = KwargParameter, "," => ActionFn(1412); + // ParameterList = KwargParameter, "," => ActionFn(1419); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant10(__symbols); + let __sym0 = __pop_Variant8(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1412::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (2, 208) + let __nt = super::__action1419::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (2, 211) } - pub(crate) fn __reduce709< + pub(crate) fn __reduce713< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27300,15 +27390,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList = KwargParameter => ActionFn(1413); - let __sym0 = __pop_Variant10(__symbols); + // ParameterList = KwargParameter => ActionFn(1420); + let __sym0 = __pop_Variant8(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1413::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant47(__nt), __end)); - (1, 208) + let __nt = super::__action1420::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant45(__nt), __end)); + (1, 211) } - pub(crate) fn __reduce710< + pub(crate) fn __reduce714< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27316,15 +27406,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList? = ParameterList => ActionFn(258); - let __sym0 = __pop_Variant47(__symbols); + // ParameterList? = ParameterList => ActionFn(260); + let __sym0 = __pop_Variant45(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action258::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant48(__nt), __end)); - (1, 209) + let __nt = super::__action260::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant46(__nt), __end)); + (1, 212) } - pub(crate) fn __reduce711< + pub(crate) fn __reduce715< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27332,14 +27422,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ParameterList? = => ActionFn(259); + // ParameterList? = => ActionFn(261); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action259::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant48(__nt), __end)); - (0, 209) + let __nt = super::__action261::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant46(__nt), __end)); + (0, 212) } - pub(crate) fn __reduce730< + pub(crate) fn __reduce734< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27347,15 +27437,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // PassStatement = "pass" => ActionFn(1415); + // PassStatement = "pass" => ActionFn(1422); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1415::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 213) + let __nt = super::__action1422::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 216) } - pub(crate) fn __reduce731< + pub(crate) fn __reduce735< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27363,15 +27453,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Pattern = AsPattern => ActionFn(91); - let __sym0 = __pop_Variant36(__symbols); + // Pattern = AsPattern => ActionFn(93); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action91::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 214) + let __nt = super::__action93::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 217) } - pub(crate) fn __reduce732< + pub(crate) fn __reduce736< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27379,15 +27469,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Pattern = OrPattern => ActionFn(92); - let __sym0 = __pop_Variant36(__symbols); + // Pattern = OrPattern => ActionFn(94); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action92::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 214) + let __nt = super::__action94::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 217) } - pub(crate) fn __reduce733< + pub(crate) fn __reduce737< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27395,15 +27485,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Pattern? = Pattern => ActionFn(400); - let __sym0 = __pop_Variant36(__symbols); + // Pattern? = Pattern => ActionFn(407); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action400::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant84(__nt), __end)); - (1, 215) + let __nt = super::__action407::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant83(__nt), __end)); + (1, 218) } - pub(crate) fn __reduce734< + pub(crate) fn __reduce738< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27411,14 +27501,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Pattern? = => ActionFn(401); + // Pattern? = => ActionFn(408); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action401::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant84(__nt), __end)); - (0, 215) + let __nt = super::__action408::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant83(__nt), __end)); + (0, 218) } - pub(crate) fn __reduce735< + pub(crate) fn __reduce739< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27426,17 +27516,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Patterns = Pattern, "," => ActionFn(1416); + // Patterns = Pattern, "," => ActionFn(1423); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1416::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 216) + let __nt = super::__action1423::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 219) } - pub(crate) fn __reduce736< + pub(crate) fn __reduce740< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27444,17 +27534,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Patterns = TwoOrMore, "," => ActionFn(1417); + // Patterns = TwoOrMore, "," => ActionFn(1424); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant53(__symbols); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1417::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 216) + let __nt = super::__action1424::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 219) } - pub(crate) fn __reduce737< + pub(crate) fn __reduce741< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27462,15 +27552,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Patterns = TwoOrMore => ActionFn(1418); - let __sym0 = __pop_Variant53(__symbols); + // Patterns = TwoOrMore => ActionFn(1425); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1418::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 216) + let __nt = super::__action1425::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 219) } - pub(crate) fn __reduce738< + pub(crate) fn __reduce742< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27478,15 +27568,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Patterns = Pattern => ActionFn(90); - let __sym0 = __pop_Variant36(__symbols); + // Patterns = Pattern => ActionFn(92); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action90::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 216) + let __nt = super::__action92::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 219) } - pub(crate) fn __reduce739< + pub(crate) fn __reduce743< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27494,18 +27584,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Power<"all"> = AtomExpr<"all">, "**", Factor<"all"> => ActionFn(1419); + // Power<"all"> = AtomExpr<"all">, "**", Factor<"all"> => ActionFn(1426); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1419::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 217) + let __nt = super::__action1426::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 220) } - pub(crate) fn __reduce740< + pub(crate) fn __reduce744< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27513,15 +27603,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Power<"all"> = AtomExpr<"all"> => ActionFn(506); - let __sym0 = __pop_Variant16(__symbols); + // Power<"all"> = AtomExpr<"all"> => ActionFn(509); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action506::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 217) + let __nt = super::__action509::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 220) } - pub(crate) fn __reduce741< + pub(crate) fn __reduce745< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27529,18 +27619,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Power<"no-withitems"> = AtomExpr<"all">, "**", Factor<"all"> => ActionFn(1420); + // Power<"no-withitems"> = AtomExpr<"all">, "**", Factor<"all"> => ActionFn(1427); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1420::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 218) + let __nt = super::__action1427::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 221) } - pub(crate) fn __reduce742< + pub(crate) fn __reduce746< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27548,15 +27638,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Power<"no-withitems"> = AtomExpr<"no-withitems"> => ActionFn(555); - let __sym0 = __pop_Variant16(__symbols); + // Power<"no-withitems"> = AtomExpr<"no-withitems"> => ActionFn(560); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action555::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 218) + let __nt = super::__action560::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 221) } - pub(crate) fn __reduce743< + pub(crate) fn __reduce747< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27568,10 +27658,10 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action3::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (0, 219) + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (0, 222) } - pub(crate) fn __reduce744< + pub(crate) fn __reduce748< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27581,15 +27671,15 @@ mod __parse__Top { { // Program = Program, CompoundStatement => ActionFn(4); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action4::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (2, 219) + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (2, 222) } - pub(crate) fn __reduce745< + pub(crate) fn __reduce749< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27597,19 +27687,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Program = Program, SmallStatement, ";", "\n" => ActionFn(1166); + // Program = Program, SmallStatement, ";", "\n" => ActionFn(1170); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1166::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (4, 219) + let __nt = super::__action1170::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (4, 222) } - pub(crate) fn __reduce746< + pub(crate) fn __reduce750< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27617,20 +27707,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Program = Program, ( ";")+, SmallStatement, ";", "\n" => ActionFn(1167); + // Program = Program, ( ";")+, SmallStatement, ";", "\n" => ActionFn(1171); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant38(__symbols); - let __sym1 = __pop_Variant39(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant37(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1167::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (5, 219) + let __nt = super::__action1171::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (5, 222) } - pub(crate) fn __reduce747< + pub(crate) fn __reduce751< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27638,18 +27728,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Program = Program, SmallStatement, "\n" => ActionFn(1168); + // Program = Program, SmallStatement, "\n" => ActionFn(1172); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1168::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (3, 219) + let __nt = super::__action1172::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (3, 222) } - pub(crate) fn __reduce748< + pub(crate) fn __reduce752< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27657,19 +27747,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Program = Program, ( ";")+, SmallStatement, "\n" => ActionFn(1169); + // Program = Program, ( ";")+, SmallStatement, "\n" => ActionFn(1173); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant38(__symbols); - let __sym1 = __pop_Variant39(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant37(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1169::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (4, 219) + let __nt = super::__action1173::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (4, 222) } - pub(crate) fn __reduce749< + pub(crate) fn __reduce753< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27680,14 +27770,14 @@ mod __parse__Top { // Program = Program, "\n" => ActionFn(6); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant26(__symbols); + let __sym0 = __pop_Variant24(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action6::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (2, 219) + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (2, 222) } - pub(crate) fn __reduce750< + pub(crate) fn __reduce754< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27695,15 +27785,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // RaiseStatement = "raise" => ActionFn(1421); + // RaiseStatement = "raise" => ActionFn(1428); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1421::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 220) + let __nt = super::__action1428::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 223) } - pub(crate) fn __reduce751< + pub(crate) fn __reduce755< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27711,19 +27801,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // RaiseStatement = "raise", Test<"all">, "from", Test<"all"> => ActionFn(1422); + // RaiseStatement = "raise", Test<"all">, "from", Test<"all"> => ActionFn(1429); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1422::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 220) + let __nt = super::__action1429::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 223) } - pub(crate) fn __reduce752< + pub(crate) fn __reduce756< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27731,17 +27821,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // RaiseStatement = "raise", Test<"all"> => ActionFn(1423); + // RaiseStatement = "raise", Test<"all"> => ActionFn(1430); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1423::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (2, 220) + let __nt = super::__action1430::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (2, 223) } - pub(crate) fn __reduce753< + pub(crate) fn __reduce757< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27749,18 +27839,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "(", Pattern, ")" => ActionFn(1424); + // SequencePattern = "(", Pattern, ")" => ActionFn(1431); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant34(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1424::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 221) + let __nt = super::__action1431::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 224) } - pub(crate) fn __reduce754< + pub(crate) fn __reduce758< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27768,17 +27858,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "(", ")" => ActionFn(1425); + // SequencePattern = "(", ")" => ActionFn(1432); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1425::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 221) + let __nt = super::__action1432::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 224) } - pub(crate) fn __reduce755< + pub(crate) fn __reduce759< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27786,19 +27876,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "(", Pattern, ",", ")" => ActionFn(1426); + // SequencePattern = "(", Pattern, ",", ")" => ActionFn(1433); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant34(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1426::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 221) + let __nt = super::__action1433::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 224) } - pub(crate) fn __reduce756< + pub(crate) fn __reduce760< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27806,20 +27896,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "(", ( ",")+, Pattern, ",", ")" => ActionFn(1427); + // SequencePattern = "(", ( ",")+, Pattern, ",", ")" => ActionFn(1434); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant36(__symbols); - let __sym1 = __pop_Variant37(__symbols); + let __sym2 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant35(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1427::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (5, 221) + let __nt = super::__action1434::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (5, 224) } - pub(crate) fn __reduce757< + pub(crate) fn __reduce761< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27827,19 +27917,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "(", ( ",")+, Pattern, ")" => ActionFn(1428); + // SequencePattern = "(", ( ",")+, Pattern, ")" => ActionFn(1435); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant36(__symbols); - let __sym1 = __pop_Variant37(__symbols); + let __sym2 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant35(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1428::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 221) + let __nt = super::__action1435::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 224) } - pub(crate) fn __reduce758< + pub(crate) fn __reduce762< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27847,18 +27937,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "[", Pattern, "]" => ActionFn(1519); + // SequencePattern = "[", Pattern, "]" => ActionFn(1526); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant34(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1519::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 221) + let __nt = super::__action1526::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 224) } - pub(crate) fn __reduce759< + pub(crate) fn __reduce763< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27866,17 +27956,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "[", "]" => ActionFn(1520); + // SequencePattern = "[", "]" => ActionFn(1527); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1520::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 221) + let __nt = super::__action1527::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 224) } - pub(crate) fn __reduce760< + pub(crate) fn __reduce764< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27884,19 +27974,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "[", ( ",")+, Pattern, "]" => ActionFn(1521); + // SequencePattern = "[", ( ",")+, Pattern, "]" => ActionFn(1528); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant36(__symbols); - let __sym1 = __pop_Variant37(__symbols); + let __sym2 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant35(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1521::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (4, 221) + let __nt = super::__action1528::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (4, 224) } - pub(crate) fn __reduce761< + pub(crate) fn __reduce765< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27904,18 +27994,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SequencePattern = "[", ( ",")+, "]" => ActionFn(1522); + // SequencePattern = "[", ( ",")+, "]" => ActionFn(1529); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant37(__symbols); + let __sym1 = __pop_Variant35(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1522::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (3, 221) + let __nt = super::__action1529::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (3, 224) } - pub(crate) fn __reduce762< + pub(crate) fn __reduce766< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27923,17 +28013,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SetLiteralValues = OneOrMore, "," => ActionFn(638); + // SetLiteralValues = OneOrMore, "," => ActionFn(643); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action638::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (2, 222) + let __nt = super::__action643::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (2, 225) } - pub(crate) fn __reduce763< + pub(crate) fn __reduce767< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27941,15 +28031,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SetLiteralValues = OneOrMore => ActionFn(639); - let __sym0 = __pop_Variant34(__symbols); + // SetLiteralValues = OneOrMore => ActionFn(644); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action639::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (1, 222) + let __nt = super::__action644::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (1, 225) } - pub(crate) fn __reduce764< + pub(crate) fn __reduce768< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27957,18 +28047,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftExpression<"all"> = ShiftExpression<"all">, ShiftOp, ArithmeticExpression<"all"> => ActionFn(1430); + // ShiftExpression<"all"> = ShiftExpression<"all">, ShiftOp, ArithmeticExpression<"all"> => ActionFn(1437); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1430::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 223) + let __nt = super::__action1437::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 226) } - pub(crate) fn __reduce765< + pub(crate) fn __reduce769< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27976,15 +28066,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftExpression<"all"> = ArithmeticExpression<"all"> => ActionFn(485); - let __sym0 = __pop_Variant16(__symbols); + // ShiftExpression<"all"> = ArithmeticExpression<"all"> => ActionFn(484); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action485::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 223) + let __nt = super::__action484::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 226) } - pub(crate) fn __reduce766< + pub(crate) fn __reduce770< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -27992,18 +28082,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftExpression<"no-withitems"> = ShiftExpression<"all">, ShiftOp, ArithmeticExpression<"all"> => ActionFn(1431); + // ShiftExpression<"no-withitems"> = ShiftExpression<"all">, ShiftOp, ArithmeticExpression<"all"> => ActionFn(1438); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1431::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 224) + let __nt = super::__action1438::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 227) } - pub(crate) fn __reduce767< + pub(crate) fn __reduce771< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28011,15 +28101,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftExpression<"no-withitems"> = ArithmeticExpression<"no-withitems"> => ActionFn(512); - let __sym0 = __pop_Variant16(__symbols); + // ShiftExpression<"no-withitems"> = ArithmeticExpression<"no-withitems"> => ActionFn(521); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action512::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 224) + let __nt = super::__action521::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 227) } - pub(crate) fn __reduce768< + pub(crate) fn __reduce772< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28027,15 +28117,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftOp = "<<" => ActionFn(192); + // ShiftOp = "<<" => ActionFn(196); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action192::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 225) + let __nt = super::__action196::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 228) } - pub(crate) fn __reduce769< + pub(crate) fn __reduce773< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28043,15 +28133,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ShiftOp = ">>" => ActionFn(193); + // ShiftOp = ">>" => ActionFn(197); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action193::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant50(__nt), __end)); - (1, 225) + let __nt = super::__action197::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant48(__nt), __end)); + (1, 228) } - pub(crate) fn __reduce770< + pub(crate) fn __reduce774< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28059,20 +28149,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension = "async", "for", ExpressionList, "in", OrTest<"all"> => ActionFn(1525); + // SingleForComprehension = "async", "for", ExpressionList, "in", OrTest<"all"> => ActionFn(1532); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1525::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant85(__nt), __end)); - (5, 226) + let __nt = super::__action1532::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant84(__nt), __end)); + (5, 229) } - pub(crate) fn __reduce771< + pub(crate) fn __reduce775< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28080,21 +28170,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension = "async", "for", ExpressionList, "in", OrTest<"all">, ComprehensionIf+ => ActionFn(1526); + // SingleForComprehension = "async", "for", ExpressionList, "in", OrTest<"all">, ComprehensionIf+ => ActionFn(1533); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant18(__symbols); - let __sym4 = __pop_Variant16(__symbols); + let __sym5 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1526::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant85(__nt), __end)); - (6, 226) + let __nt = super::__action1533::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant84(__nt), __end)); + (6, 229) } - pub(crate) fn __reduce772< + pub(crate) fn __reduce776< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28102,19 +28192,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension = "for", ExpressionList, "in", OrTest<"all"> => ActionFn(1527); + // SingleForComprehension = "for", ExpressionList, "in", OrTest<"all"> => ActionFn(1534); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1527::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant85(__nt), __end)); - (4, 226) + let __nt = super::__action1534::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant84(__nt), __end)); + (4, 229) } - pub(crate) fn __reduce773< + pub(crate) fn __reduce777< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28122,20 +28212,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension = "for", ExpressionList, "in", OrTest<"all">, ComprehensionIf+ => ActionFn(1528); + // SingleForComprehension = "for", ExpressionList, "in", OrTest<"all">, ComprehensionIf+ => ActionFn(1535); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant18(__symbols); - let __sym3 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1528::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant85(__nt), __end)); - (5, 226) + let __nt = super::__action1535::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant84(__nt), __end)); + (5, 229) } - pub(crate) fn __reduce774< + pub(crate) fn __reduce778< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28143,15 +28233,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension+ = SingleForComprehension => ActionFn(242); - let __sym0 = __pop_Variant85(__symbols); + // SingleForComprehension+ = SingleForComprehension => ActionFn(246); + let __sym0 = __pop_Variant84(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action242::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant86(__nt), __end)); - (1, 227) + let __nt = super::__action246::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant85(__nt), __end)); + (1, 230) } - pub(crate) fn __reduce775< + pub(crate) fn __reduce779< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28159,17 +28249,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SingleForComprehension+ = SingleForComprehension+, SingleForComprehension => ActionFn(243); + // SingleForComprehension+ = SingleForComprehension+, SingleForComprehension => ActionFn(247); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant85(__symbols); - let __sym0 = __pop_Variant86(__symbols); + let __sym1 = __pop_Variant84(__symbols); + let __sym0 = __pop_Variant85(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action243::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant86(__nt), __end)); - (2, 227) + let __nt = super::__action247::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant85(__nt), __end)); + (2, 230) } - pub(crate) fn __reduce776< + pub(crate) fn __reduce780< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28177,17 +28267,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SliceOp = ":", Test<"all"> => ActionFn(1687); + // SliceOp = ":", Test<"all"> => ActionFn(1694); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1687::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant87(__nt), __end)); - (2, 228) + let __nt = super::__action1694::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant86(__nt), __end)); + (2, 231) } - pub(crate) fn __reduce777< + pub(crate) fn __reduce781< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28195,15 +28285,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SliceOp = ":" => ActionFn(1688); + // SliceOp = ":" => ActionFn(1695); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1688::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant87(__nt), __end)); - (1, 228) + let __nt = super::__action1695::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant86(__nt), __end)); + (1, 231) } - pub(crate) fn __reduce778< + pub(crate) fn __reduce782< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28211,15 +28301,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SliceOp? = SliceOp => ActionFn(254); - let __sym0 = __pop_Variant87(__symbols); + // SliceOp? = SliceOp => ActionFn(256); + let __sym0 = __pop_Variant86(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action254::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant88(__nt), __end)); - (1, 229) + let __nt = super::__action256::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant87(__nt), __end)); + (1, 232) } - pub(crate) fn __reduce779< + pub(crate) fn __reduce783< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28227,14 +28317,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SliceOp? = => ActionFn(255); + // SliceOp? = => ActionFn(257); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action255::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant88(__nt), __end)); - (0, 229) + let __nt = super::__action257::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant87(__nt), __end)); + (0, 232) } - pub(crate) fn __reduce780< + pub(crate) fn __reduce784< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28243,14 +28333,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = ExpressionStatement => ActionFn(13); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action13::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce781< + pub(crate) fn __reduce785< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28259,14 +28349,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = PassStatement => ActionFn(14); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action14::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce782< + pub(crate) fn __reduce786< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28275,14 +28365,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = DelStatement => ActionFn(15); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action15::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce783< + pub(crate) fn __reduce787< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28291,14 +28381,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = FlowStatement => ActionFn(16); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action16::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce784< + pub(crate) fn __reduce788< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28307,14 +28397,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = ImportStatement => ActionFn(17); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action17::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce785< + pub(crate) fn __reduce789< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28323,14 +28413,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = GlobalStatement => ActionFn(18); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action18::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce786< + pub(crate) fn __reduce790< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28339,14 +28429,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = NonlocalStatement => ActionFn(19); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action19::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce787< + pub(crate) fn __reduce791< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28355,14 +28445,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = AssertStatement => ActionFn(20); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action20::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce788< + pub(crate) fn __reduce792< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28371,14 +28461,14 @@ mod __parse__Top { ) -> (usize, usize) { // SmallStatement = TypeAliasStatement => ActionFn(21); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action21::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce789< + pub(crate) fn __reduce793< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28386,15 +28476,31 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SmallStatement = LineMagicStatement => ActionFn(22); - let __sym0 = __pop_Variant38(__symbols); + // SmallStatement = IpyEscapeCommandStatement => ActionFn(22); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action22::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (1, 230) + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) } - pub(crate) fn __reduce790< + pub(crate) fn __reduce794< + >( + mode: Mode, + __lookahead_start: Option<&TextSize>, + __symbols: &mut alloc::vec::Vec<(TextSize,__Symbol<>,TextSize)>, + _: core::marker::PhantomData<()>, + ) -> (usize, usize) + { + // SmallStatement = IpyHelpEndEscapeCommandStatement => ActionFn(23); + let __sym0 = __pop_Variant36(__symbols); + let __start = __sym0.0; + let __end = __sym0.2; + let __nt = super::__action23::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (1, 233) + } + pub(crate) fn __reduce795< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28402,17 +28508,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarExpr = "*", Expression<"all"> => ActionFn(1434); + // StarExpr = "*", Expression<"all"> => ActionFn(1441); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1434::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 231) + let __nt = super::__action1441::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 234) } - pub(crate) fn __reduce791< + pub(crate) fn __reduce796< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28420,17 +28526,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarPattern = "*", Identifier => ActionFn(1435); + // StarPattern = "*", Identifier => ActionFn(1442); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1435::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (2, 232) + let __nt = super::__action1442::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (2, 235) } - pub(crate) fn __reduce792< + pub(crate) fn __reduce797< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28438,18 +28544,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarTypedParameter = Identifier, ":", TestOrStarExpr => ActionFn(1436); + // StarTypedParameter = Identifier, ":", TestOrStarExpr => ActionFn(1443); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1436::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant64(__nt), __end)); - (3, 233) + let __nt = super::__action1443::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant63(__nt), __end)); + (3, 236) } - pub(crate) fn __reduce793< + pub(crate) fn __reduce798< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28457,15 +28563,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarTypedParameter = Identifier => ActionFn(1437); - let __sym0 = __pop_Variant24(__symbols); + // StarTypedParameter = Identifier => ActionFn(1444); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1437::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant64(__nt), __end)); - (1, 233) + let __nt = super::__action1444::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant63(__nt), __end)); + (1, 236) } - pub(crate) fn __reduce794< + pub(crate) fn __reduce799< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28473,15 +28579,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarTypedParameter? = StarTypedParameter => ActionFn(472); - let __sym0 = __pop_Variant64(__symbols); + // StarTypedParameter? = StarTypedParameter => ActionFn(475); + let __sym0 = __pop_Variant63(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action472::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (1, 234) + let __nt = super::__action475::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (1, 237) } - pub(crate) fn __reduce795< + pub(crate) fn __reduce800< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28489,14 +28595,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarTypedParameter? = => ActionFn(473); + // StarTypedParameter? = => ActionFn(476); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action473::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (0, 234) + let __nt = super::__action476::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (0, 237) } - pub(crate) fn __reduce796< + pub(crate) fn __reduce801< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28504,15 +28610,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarUntypedParameter = Identifier => ActionFn(1438); - let __sym0 = __pop_Variant24(__symbols); + // StarUntypedParameter = Identifier => ActionFn(1445); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1438::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant64(__nt), __end)); - (1, 235) + let __nt = super::__action1445::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant63(__nt), __end)); + (1, 238) } - pub(crate) fn __reduce797< + pub(crate) fn __reduce802< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28520,15 +28626,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarUntypedParameter? = StarUntypedParameter => ActionFn(461); - let __sym0 = __pop_Variant64(__symbols); + // StarUntypedParameter? = StarUntypedParameter => ActionFn(464); + let __sym0 = __pop_Variant63(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action461::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (1, 236) + let __nt = super::__action464::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (1, 239) } - pub(crate) fn __reduce798< + pub(crate) fn __reduce803< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28536,14 +28642,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // StarUntypedParameter? = => ActionFn(462); + // StarUntypedParameter? = => ActionFn(465); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action462::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant65(__nt), __end)); - (0, 236) + let __nt = super::__action465::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant64(__nt), __end)); + (0, 239) } - pub(crate) fn __reduce799< + pub(crate) fn __reduce804< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28551,18 +28657,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = SmallStatement, ";", "\n" => ActionFn(1170); + // Statements = SmallStatement, ";", "\n" => ActionFn(1174); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1170::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (3, 237) + let __nt = super::__action1174::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (3, 240) } - pub(crate) fn __reduce800< + pub(crate) fn __reduce805< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28570,19 +28676,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = ( ";")+, SmallStatement, ";", "\n" => ActionFn(1171); + // Statements = ( ";")+, SmallStatement, ";", "\n" => ActionFn(1175); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant39(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1171::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (4, 237) + let __nt = super::__action1175::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (4, 240) } - pub(crate) fn __reduce801< + pub(crate) fn __reduce806< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28590,17 +28696,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = SmallStatement, "\n" => ActionFn(1172); + // Statements = SmallStatement, "\n" => ActionFn(1176); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1172::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (2, 237) + let __nt = super::__action1176::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (2, 240) } - pub(crate) fn __reduce802< + pub(crate) fn __reduce807< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28608,18 +28714,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = ( ";")+, SmallStatement, "\n" => ActionFn(1173); + // Statements = ( ";")+, SmallStatement, "\n" => ActionFn(1177); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant39(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1173::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (3, 237) + let __nt = super::__action1177::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (3, 240) } - pub(crate) fn __reduce803< + pub(crate) fn __reduce808< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28628,14 +28734,14 @@ mod __parse__Top { ) -> (usize, usize) { // Statements = CompoundStatement => ActionFn(10); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action10::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (1, 237) + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (1, 240) } - pub(crate) fn __reduce804< + pub(crate) fn __reduce809< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28645,15 +28751,15 @@ mod __parse__Top { { // Statements = Statements, CompoundStatement => ActionFn(11); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant89(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant88(__symbols); let __start = __sym0.0; let __end = __sym1.2; let __nt = super::__action11::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (2, 237) + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (2, 240) } - pub(crate) fn __reduce805< + pub(crate) fn __reduce810< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28661,19 +28767,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = Statements, SmallStatement, ";", "\n" => ActionFn(1174); + // Statements = Statements, SmallStatement, ";", "\n" => ActionFn(1178); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant89(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant88(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1174::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (4, 237) + let __nt = super::__action1178::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (4, 240) } - pub(crate) fn __reduce806< + pub(crate) fn __reduce811< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28681,20 +28787,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = Statements, ( ";")+, SmallStatement, ";", "\n" => ActionFn(1175); + // Statements = Statements, ( ";")+, SmallStatement, ";", "\n" => ActionFn(1179); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant38(__symbols); - let __sym1 = __pop_Variant39(__symbols); - let __sym0 = __pop_Variant89(__symbols); + let __sym2 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant37(__symbols); + let __sym0 = __pop_Variant88(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1175::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (5, 237) + let __nt = super::__action1179::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (5, 240) } - pub(crate) fn __reduce807< + pub(crate) fn __reduce812< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28702,18 +28808,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = Statements, SmallStatement, "\n" => ActionFn(1176); + // Statements = Statements, SmallStatement, "\n" => ActionFn(1180); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant89(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant88(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1176::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (3, 237) + let __nt = super::__action1180::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (3, 240) } - pub(crate) fn __reduce808< + pub(crate) fn __reduce813< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28721,19 +28827,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Statements = Statements, ( ";")+, SmallStatement, "\n" => ActionFn(1177); + // Statements = Statements, ( ";")+, SmallStatement, "\n" => ActionFn(1181); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant38(__symbols); - let __sym1 = __pop_Variant39(__symbols); - let __sym0 = __pop_Variant89(__symbols); + let __sym2 = __pop_Variant36(__symbols); + let __sym1 = __pop_Variant37(__symbols); + let __sym0 = __pop_Variant88(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1177::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant89(__nt), __end)); - (4, 237) + let __nt = super::__action1181::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant88(__nt), __end)); + (4, 240) } - pub(crate) fn __reduce809< + pub(crate) fn __reduce814< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28741,15 +28847,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = TestOrStarNamedExpr => ActionFn(207); - let __sym0 = __pop_Variant16(__symbols); + // Subscript = TestOrStarNamedExpr => ActionFn(211); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action207::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 238) + let __nt = super::__action211::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 241) } - pub(crate) fn __reduce810< + pub(crate) fn __reduce815< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28757,19 +28863,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = Test<"all">, ":", Test<"all">, SliceOp => ActionFn(1689); + // Subscript = Test<"all">, ":", Test<"all">, SliceOp => ActionFn(1696); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant87(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant86(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1689::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (4, 238) + let __nt = super::__action1696::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (4, 241) } - pub(crate) fn __reduce811< + pub(crate) fn __reduce816< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28777,18 +28883,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = Test<"all">, ":", SliceOp => ActionFn(1690); + // Subscript = Test<"all">, ":", SliceOp => ActionFn(1697); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant87(__symbols); + let __sym2 = __pop_Variant86(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1690::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 238) + let __nt = super::__action1697::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 241) } - pub(crate) fn __reduce812< + pub(crate) fn __reduce817< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28796,18 +28902,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = ":", Test<"all">, SliceOp => ActionFn(1691); + // Subscript = ":", Test<"all">, SliceOp => ActionFn(1698); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant87(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant86(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1691::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 238) + let __nt = super::__action1698::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 241) } - pub(crate) fn __reduce813< + pub(crate) fn __reduce818< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28815,17 +28921,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = ":", SliceOp => ActionFn(1692); + // Subscript = ":", SliceOp => ActionFn(1699); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant87(__symbols); + let __sym1 = __pop_Variant86(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1692::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 238) + let __nt = super::__action1699::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 241) } - pub(crate) fn __reduce814< + pub(crate) fn __reduce819< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28833,18 +28939,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = Test<"all">, ":", Test<"all"> => ActionFn(1693); + // Subscript = Test<"all">, ":", Test<"all"> => ActionFn(1700); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1693::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 238) + let __nt = super::__action1700::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 241) } - pub(crate) fn __reduce815< + pub(crate) fn __reduce820< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28852,17 +28958,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = Test<"all">, ":" => ActionFn(1694); + // Subscript = Test<"all">, ":" => ActionFn(1701); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1694::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 238) + let __nt = super::__action1701::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 241) } - pub(crate) fn __reduce816< + pub(crate) fn __reduce821< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28870,17 +28976,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = ":", Test<"all"> => ActionFn(1695); + // Subscript = ":", Test<"all"> => ActionFn(1702); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1695::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 238) + let __nt = super::__action1702::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 241) } - pub(crate) fn __reduce817< + pub(crate) fn __reduce822< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28888,15 +28994,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Subscript = ":" => ActionFn(1696); + // Subscript = ":" => ActionFn(1703); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1696::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 238) + let __nt = super::__action1703::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 241) } - pub(crate) fn __reduce818< + pub(crate) fn __reduce823< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28904,15 +29010,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SubscriptList = Subscript => ActionFn(1440); - let __sym0 = __pop_Variant16(__symbols); + // SubscriptList = Subscript => ActionFn(1447); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1440::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 239) + let __nt = super::__action1447::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 242) } - pub(crate) fn __reduce819< + pub(crate) fn __reduce824< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28920,17 +29026,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SubscriptList = Subscript, "," => ActionFn(1441); + // SubscriptList = Subscript, "," => ActionFn(1448); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1441::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 239) + let __nt = super::__action1448::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 242) } - pub(crate) fn __reduce820< + pub(crate) fn __reduce825< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28938,17 +29044,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SubscriptList = TwoOrMore, "," => ActionFn(1442); + // SubscriptList = TwoOrMore, "," => ActionFn(1449); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1442::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 239) + let __nt = super::__action1449::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 242) } - pub(crate) fn __reduce821< + pub(crate) fn __reduce826< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28956,15 +29062,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // SubscriptList = TwoOrMore => ActionFn(1443); - let __sym0 = __pop_Variant34(__symbols); + // SubscriptList = TwoOrMore => ActionFn(1450); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1443::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 239) + let __nt = super::__action1450::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 242) } - pub(crate) fn __reduce822< + pub(crate) fn __reduce827< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28972,18 +29078,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Suite = SmallStatement, ";", "\n" => ActionFn(1178); + // Suite = SmallStatement, ";", "\n" => ActionFn(1182); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1178::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (3, 240) + let __nt = super::__action1182::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (3, 243) } - pub(crate) fn __reduce823< + pub(crate) fn __reduce828< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -28991,19 +29097,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Suite = ( ";")+, SmallStatement, ";", "\n" => ActionFn(1179); + // Suite = ( ";")+, SmallStatement, ";", "\n" => ActionFn(1183); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant39(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1179::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (4, 240) + let __nt = super::__action1183::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (4, 243) } - pub(crate) fn __reduce824< + pub(crate) fn __reduce829< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29011,17 +29117,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Suite = SmallStatement, "\n" => ActionFn(1180); + // Suite = SmallStatement, "\n" => ActionFn(1184); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant38(__symbols); + let __sym0 = __pop_Variant36(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1180::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (2, 240) + let __nt = super::__action1184::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (2, 243) } - pub(crate) fn __reduce825< + pub(crate) fn __reduce830< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29029,18 +29135,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Suite = ( ";")+, SmallStatement, "\n" => ActionFn(1181); + // Suite = ( ";")+, SmallStatement, "\n" => ActionFn(1185); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant38(__symbols); - let __sym0 = __pop_Variant39(__symbols); + let __sym1 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant37(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1181::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (3, 240) + let __nt = super::__action1185::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (3, 243) } - pub(crate) fn __reduce826< + pub(crate) fn __reduce831< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29051,16 +29157,16 @@ mod __parse__Top { // Suite = "\n", Indent, Statements, Dedent => ActionFn(8); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant89(__symbols); + let __sym2 = __pop_Variant88(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; let __nt = super::__action8::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant26(__nt), __end)); - (4, 240) + __symbols.push((__start, __Symbol::Variant24(__nt), __end)); + (4, 243) } - pub(crate) fn __reduce827< + pub(crate) fn __reduce832< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29068,18 +29174,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Term<"all"> = Term<"all">, MulOp, Factor<"all"> => ActionFn(1444); + // Term<"all"> = Term<"all">, MulOp, Factor<"all"> => ActionFn(1451); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1444::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 241) + let __nt = super::__action1451::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 244) } - pub(crate) fn __reduce828< + pub(crate) fn __reduce833< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29087,15 +29193,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Term<"all"> = Factor<"all"> => ActionFn(498); - let __sym0 = __pop_Variant16(__symbols); + // Term<"all"> = Factor<"all"> => ActionFn(501); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action498::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 241) + let __nt = super::__action501::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 244) } - pub(crate) fn __reduce829< + pub(crate) fn __reduce834< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29103,18 +29209,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Term<"no-withitems"> = Term<"all">, MulOp, Factor<"all"> => ActionFn(1445); + // Term<"no-withitems"> = Term<"all">, MulOp, Factor<"all"> => ActionFn(1452); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant50(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); + let __sym1 = __pop_Variant48(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1445::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 242) + let __nt = super::__action1452::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 245) } - pub(crate) fn __reduce830< + pub(crate) fn __reduce835< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29122,15 +29228,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Term<"no-withitems"> = Factor<"no-withitems"> => ActionFn(539); - let __sym0 = __pop_Variant16(__symbols); + // Term<"no-withitems"> = Factor<"no-withitems"> => ActionFn(554); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action539::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 242) + let __nt = super::__action554::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 245) } - pub(crate) fn __reduce831< + pub(crate) fn __reduce836< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29138,20 +29244,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"all"> = OrTest<"all">, "if", OrTest<"all">, "else", Test<"all"> => ActionFn(1446); + // Test<"all"> = OrTest<"all">, "if", OrTest<"all">, "else", Test<"all"> => ActionFn(1453); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1446::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 243) + let __nt = super::__action1453::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 246) } - pub(crate) fn __reduce832< + pub(crate) fn __reduce837< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29159,15 +29265,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"all"> = OrTest<"all"> => ActionFn(377); - let __sym0 = __pop_Variant16(__symbols); + // Test<"all"> = OrTest<"all"> => ActionFn(382); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action377::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 243) + let __nt = super::__action382::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 246) } - pub(crate) fn __reduce833< + pub(crate) fn __reduce838< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29175,15 +29281,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"all"> = LambdaDef => ActionFn(378); - let __sym0 = __pop_Variant16(__symbols); + // Test<"all"> = LambdaDef => ActionFn(383); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action378::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 243) + let __nt = super::__action383::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 246) } - pub(crate) fn __reduce834< + pub(crate) fn __reduce839< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29192,14 +29298,14 @@ mod __parse__Top { ) -> (usize, usize) { // Test<"all">? = Test<"all"> => ActionFn(304); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; let __nt = super::__action304::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (1, 244) + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (1, 247) } - pub(crate) fn __reduce835< + pub(crate) fn __reduce840< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29211,10 +29317,10 @@ mod __parse__Top { let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); let __nt = super::__action305::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 244) + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (0, 247) } - pub(crate) fn __reduce836< + pub(crate) fn __reduce841< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29222,20 +29328,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"no-withitems"> = OrTest<"all">, "if", OrTest<"all">, "else", Test<"all"> => ActionFn(1447); + // Test<"no-withitems"> = OrTest<"all">, "if", OrTest<"all">, "else", Test<"all"> => ActionFn(1454); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1447::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (5, 245) + let __nt = super::__action1454::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (5, 248) } - pub(crate) fn __reduce837< + pub(crate) fn __reduce842< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29243,15 +29349,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"no-withitems"> = OrTest<"no-withitems"> => ActionFn(407); - let __sym0 = __pop_Variant16(__symbols); + // Test<"no-withitems"> = OrTest<"no-withitems"> => ActionFn(414); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action407::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 245) + let __nt = super::__action414::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 248) } - pub(crate) fn __reduce838< + pub(crate) fn __reduce843< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29259,15 +29365,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Test<"no-withitems"> = LambdaDef => ActionFn(408); - let __sym0 = __pop_Variant16(__symbols); + // Test<"no-withitems"> = LambdaDef => ActionFn(415); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action408::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 245) + let __nt = super::__action415::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 248) } - pub(crate) fn __reduce839< + pub(crate) fn __reduce844< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29275,15 +29381,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestList = GenericList => ActionFn(220); - let __sym0 = __pop_Variant16(__symbols); + // TestList = GenericList => ActionFn(224); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action220::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 246) + let __nt = super::__action224::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 249) } - pub(crate) fn __reduce840< + pub(crate) fn __reduce845< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29291,15 +29397,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestList? = GenericList => ActionFn(1701); - let __sym0 = __pop_Variant16(__symbols); + // TestList? = GenericList => ActionFn(1708); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1701::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (1, 247) + let __nt = super::__action1708::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (1, 250) } - pub(crate) fn __reduce841< + pub(crate) fn __reduce846< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29307,14 +29413,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestList? = => ActionFn(373); + // TestList? = => ActionFn(378); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action373::<>(mode, &__start, &__end); - __symbols.push((__start, __Symbol::Variant17(__nt), __end)); - (0, 247) + let __nt = super::__action378::<>(mode, &__start, &__end); + __symbols.push((__start, __Symbol::Variant15(__nt), __end)); + (0, 250) } - pub(crate) fn __reduce842< + pub(crate) fn __reduce847< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29322,15 +29428,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestListOrYieldExpr = GenericList => ActionFn(1702); - let __sym0 = __pop_Variant16(__symbols); + // TestListOrYieldExpr = GenericList => ActionFn(1709); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1702::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 248) + let __nt = super::__action1709::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 251) } - pub(crate) fn __reduce843< + pub(crate) fn __reduce848< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29338,15 +29444,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestListOrYieldExpr = YieldExpr => ActionFn(31); - let __sym0 = __pop_Variant16(__symbols); + // TestListOrYieldExpr = YieldExpr => ActionFn(32); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action31::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 248) + let __nt = super::__action32::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 251) } - pub(crate) fn __reduce844< + pub(crate) fn __reduce849< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29354,15 +29460,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestOrStarExpr = Test<"all"> => ActionFn(33); - let __sym0 = __pop_Variant16(__symbols); + // TestOrStarExpr = Test<"all"> => ActionFn(34); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action33::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 249) + let __nt = super::__action34::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 252) } - pub(crate) fn __reduce845< + pub(crate) fn __reduce850< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29370,15 +29476,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestOrStarExpr = StarExpr => ActionFn(34); - let __sym0 = __pop_Variant16(__symbols); + // TestOrStarExpr = StarExpr => ActionFn(35); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action34::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 249) + let __nt = super::__action35::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 252) } - pub(crate) fn __reduce846< + pub(crate) fn __reduce851< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29386,15 +29492,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestOrStarExprList = GenericList => ActionFn(1703); - let __sym0 = __pop_Variant16(__symbols); + // TestOrStarExprList = GenericList => ActionFn(1710); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1703::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 250) + let __nt = super::__action1710::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 253) } - pub(crate) fn __reduce847< + pub(crate) fn __reduce852< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29402,15 +29508,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestOrStarNamedExpr = NamedExpressionTest => ActionFn(37); - let __sym0 = __pop_Variant16(__symbols); + // TestOrStarNamedExpr = NamedExpressionTest => ActionFn(38); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action37::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 251) + let __nt = super::__action38::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 254) } - pub(crate) fn __reduce848< + pub(crate) fn __reduce853< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29418,15 +29524,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TestOrStarNamedExpr = StarExpr => ActionFn(38); - let __sym0 = __pop_Variant16(__symbols); + // TestOrStarNamedExpr = StarExpr => ActionFn(39); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action38::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 251) + let __nt = super::__action39::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 254) } - pub(crate) fn __reduce849< + pub(crate) fn __reduce854< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29434,17 +29540,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Top = StartModule, Program => ActionFn(1448); + // Top = StartModule, Program => ActionFn(1455); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant26(__symbols); + let __sym1 = __pop_Variant24(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1448::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant90(__nt), __end)); - (2, 252) + let __nt = super::__action1455::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant89(__nt), __end)); + (2, 255) } - pub(crate) fn __reduce850< + pub(crate) fn __reduce855< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29452,17 +29558,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Top = StartExpression, GenericList => ActionFn(1704); + // Top = StartExpression, GenericList => ActionFn(1711); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1704::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant90(__nt), __end)); - (2, 252) + let __nt = super::__action1711::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant89(__nt), __end)); + (2, 255) } - pub(crate) fn __reduce851< + pub(crate) fn __reduce856< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29470,18 +29576,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // Top = StartExpression, GenericList, ("\n")+ => ActionFn(1705); + // Top = StartExpression, GenericList, ("\n")+ => ActionFn(1712); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant23(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant21(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1705::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant90(__nt), __end)); - (3, 252) + let __nt = super::__action1712::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant89(__nt), __end)); + (3, 255) } - pub(crate) fn __reduce852< + pub(crate) fn __reduce857< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29489,25 +29595,25 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptClause+, "else", ":", Suite, "finally", ":", Suite => ActionFn(1451); + // TryStatement = "try", ":", Suite, ExceptClause+, "else", ":", Suite, "finally", ":", Suite => ActionFn(1458); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant26(__symbols); + let __sym9 = __pop_Variant24(__symbols); let __sym8 = __pop_Variant0(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = super::__action1451::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (10, 253) + let __nt = super::__action1458::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (10, 256) } - pub(crate) fn __reduce853< + pub(crate) fn __reduce858< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29515,22 +29621,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptClause+, "else", ":", Suite => ActionFn(1452); + // TryStatement = "try", ":", Suite, ExceptClause+, "else", ":", Suite => ActionFn(1459); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1452::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 253) + let __nt = super::__action1459::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 256) } - pub(crate) fn __reduce854< + pub(crate) fn __reduce859< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29538,22 +29644,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptClause+, "finally", ":", Suite => ActionFn(1453); + // TryStatement = "try", ":", Suite, ExceptClause+, "finally", ":", Suite => ActionFn(1460); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1453::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 253) + let __nt = super::__action1460::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 256) } - pub(crate) fn __reduce855< + pub(crate) fn __reduce860< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29561,19 +29667,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptClause+ => ActionFn(1454); + // TryStatement = "try", ":", Suite, ExceptClause+ => ActionFn(1461); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1454::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 253) + let __nt = super::__action1461::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 256) } - pub(crate) fn __reduce856< + pub(crate) fn __reduce861< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29581,25 +29687,25 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptStarClause+, "else", ":", Suite, "finally", ":", Suite => ActionFn(1455); + // TryStatement = "try", ":", Suite, ExceptStarClause+, "else", ":", Suite, "finally", ":", Suite => ActionFn(1462); assert!(__symbols.len() >= 10); - let __sym9 = __pop_Variant26(__symbols); + let __sym9 = __pop_Variant24(__symbols); let __sym8 = __pop_Variant0(__symbols); let __sym7 = __pop_Variant0(__symbols); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym9.2; - let __nt = super::__action1455::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (10, 253) + let __nt = super::__action1462::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6, __sym7, __sym8, __sym9); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (10, 256) } - pub(crate) fn __reduce857< + pub(crate) fn __reduce862< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29607,22 +29713,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptStarClause+, "else", ":", Suite => ActionFn(1456); + // TryStatement = "try", ":", Suite, ExceptStarClause+, "else", ":", Suite => ActionFn(1463); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1456::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 253) + let __nt = super::__action1463::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 256) } - pub(crate) fn __reduce858< + pub(crate) fn __reduce863< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29630,22 +29736,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptStarClause+, "finally", ":", Suite => ActionFn(1457); + // TryStatement = "try", ":", Suite, ExceptStarClause+, "finally", ":", Suite => ActionFn(1464); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1457::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 253) + let __nt = super::__action1464::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 256) } - pub(crate) fn __reduce859< + pub(crate) fn __reduce864< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29653,19 +29759,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, ExceptStarClause+ => ActionFn(1458); + // TryStatement = "try", ":", Suite, ExceptStarClause+ => ActionFn(1465); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant67(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant66(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1458::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 253) + let __nt = super::__action1465::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 256) } - pub(crate) fn __reduce860< + pub(crate) fn __reduce865< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29673,21 +29779,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TryStatement = "try", ":", Suite, "finally", ":", Suite => ActionFn(1114); + // TryStatement = "try", ":", Suite, "finally", ":", Suite => ActionFn(1118); assert!(__symbols.len() >= 6); - let __sym5 = __pop_Variant26(__symbols); + let __sym5 = __pop_Variant24(__symbols); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant26(__symbols); + let __sym2 = __pop_Variant24(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1114::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (6, 253) + let __nt = super::__action1118::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (6, 256) } - pub(crate) fn __reduce861< + pub(crate) fn __reduce866< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29697,16 +29803,16 @@ mod __parse__Top { { // TwoOrMore = ClosedPattern, "|", ClosedPattern => ActionFn(338); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action338::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (3, 254) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (3, 257) } - pub(crate) fn __reduce862< + pub(crate) fn __reduce867< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29716,16 +29822,16 @@ mod __parse__Top { { // TwoOrMore = TwoOrMore, "|", ClosedPattern => ActionFn(339); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant53(__symbols); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action339::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (3, 254) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (3, 257) } - pub(crate) fn __reduce863< + pub(crate) fn __reduce868< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29735,16 +29841,16 @@ mod __parse__Top { { // TwoOrMore = Pattern, ",", Pattern => ActionFn(340); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant36(__symbols); + let __sym0 = __pop_Variant34(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action340::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (3, 255) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (3, 258) } - pub(crate) fn __reduce864< + pub(crate) fn __reduce869< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29754,16 +29860,16 @@ mod __parse__Top { { // TwoOrMore = TwoOrMore, ",", Pattern => ActionFn(341); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant36(__symbols); + let __sym2 = __pop_Variant34(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant53(__symbols); + let __sym0 = __pop_Variant52(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action341::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant53(__nt), __end)); - (3, 255) + __symbols.push((__start, __Symbol::Variant52(__nt), __end)); + (3, 258) } - pub(crate) fn __reduce865< + pub(crate) fn __reduce870< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29771,18 +29877,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TwoOrMore = Subscript, ",", Subscript => ActionFn(256); + // TwoOrMore = Subscript, ",", Subscript => ActionFn(258); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action256::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 256) + let __nt = super::__action258::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 259) } - pub(crate) fn __reduce866< + pub(crate) fn __reduce871< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29790,18 +29896,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TwoOrMore = TwoOrMore, ",", Subscript => ActionFn(257); + // TwoOrMore = TwoOrMore, ",", Subscript => ActionFn(259); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action257::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 256) + let __nt = super::__action259::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 259) } - pub(crate) fn __reduce867< + pub(crate) fn __reduce872< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29811,16 +29917,16 @@ mod __parse__Top { { // TwoOrMore = TestOrStarNamedExpr, ",", TestOrStarNamedExpr => ActionFn(345); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action345::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 257) + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 260) } - pub(crate) fn __reduce868< + pub(crate) fn __reduce873< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29830,16 +29936,16 @@ mod __parse__Top { { // TwoOrMore = TwoOrMore, ",", TestOrStarNamedExpr => ActionFn(346); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant34(__symbols); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym2.2; let __nt = super::__action346::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant34(__nt), __end)); - (3, 257) + __symbols.push((__start, __Symbol::Variant32(__nt), __end)); + (3, 260) } - pub(crate) fn __reduce869< + pub(crate) fn __reduce874< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29847,15 +29953,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeAliasName = Identifier => ActionFn(1459); - let __sym0 = __pop_Variant24(__symbols); + // TypeAliasName = Identifier => ActionFn(1466); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1459::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 258) + let __nt = super::__action1466::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 261) } - pub(crate) fn __reduce870< + pub(crate) fn __reduce875< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29863,20 +29969,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeAliasStatement = "type", TypeAliasName, TypeParamList, "=", Test<"all"> => ActionFn(1737); + // TypeAliasStatement = "type", TypeAliasName, TypeParams, "=", Test<"all"> => ActionFn(1744); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant16(__symbols); + let __sym4 = __pop_Variant14(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant82(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant91(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1737::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 259) + let __nt = super::__action1744::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 262) } - pub(crate) fn __reduce871< + pub(crate) fn __reduce876< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29884,19 +29990,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeAliasStatement = "type", TypeAliasName, "=", Test<"all"> => ActionFn(1738); + // TypeAliasStatement = "type", TypeAliasName, "=", Test<"all"> => ActionFn(1745); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant16(__symbols); + let __sym3 = __pop_Variant14(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1738::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 259) + let __nt = super::__action1745::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 262) } - pub(crate) fn __reduce872< + pub(crate) fn __reduce877< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29904,18 +30010,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParam = Identifier, ":", Test<"all"> => ActionFn(1461); + // TypeParam = Identifier, ":", Test<"all"> => ActionFn(1468); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1461::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant91(__nt), __end)); - (3, 260) + let __nt = super::__action1468::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant90(__nt), __end)); + (3, 263) } - pub(crate) fn __reduce873< + pub(crate) fn __reduce878< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29923,15 +30029,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParam = Identifier => ActionFn(1462); - let __sym0 = __pop_Variant24(__symbols); + // TypeParam = Identifier => ActionFn(1469); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1462::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant91(__nt), __end)); - (1, 260) + let __nt = super::__action1469::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant90(__nt), __end)); + (1, 263) } - pub(crate) fn __reduce874< + pub(crate) fn __reduce879< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29939,17 +30045,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParam = "*", Identifier => ActionFn(1463); + // TypeParam = "*", Identifier => ActionFn(1470); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1463::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant91(__nt), __end)); - (2, 260) + let __nt = super::__action1470::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant90(__nt), __end)); + (2, 263) } - pub(crate) fn __reduce875< + pub(crate) fn __reduce880< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29957,17 +30063,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParam = "**", Identifier => ActionFn(1464); + // TypeParam = "**", Identifier => ActionFn(1471); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant24(__symbols); + let __sym1 = __pop_Variant22(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1464::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant91(__nt), __end)); - (2, 260) + let __nt = super::__action1471::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant90(__nt), __end)); + (2, 263) } - pub(crate) fn __reduce876< + pub(crate) fn __reduce881< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29975,19 +30081,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParamList = "[", OneOrMore, ",", "]" => ActionFn(1465); + // TypeParams = "[", OneOrMore, ",", "]" => ActionFn(1472); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant82(__symbols); + let __sym1 = __pop_Variant81(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1465::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant82(__nt), __end)); - (4, 261) + let __nt = super::__action1472::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant91(__nt), __end)); + (4, 264) } - pub(crate) fn __reduce877< + pub(crate) fn __reduce882< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -29995,18 +30101,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParamList = "[", OneOrMore, "]" => ActionFn(1466); + // TypeParams = "[", OneOrMore, "]" => ActionFn(1473); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant82(__symbols); + let __sym1 = __pop_Variant81(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1466::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant82(__nt), __end)); - (3, 261) + let __nt = super::__action1473::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant91(__nt), __end)); + (3, 264) } - pub(crate) fn __reduce878< + pub(crate) fn __reduce883< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30014,15 +30120,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParamList? = TypeParamList => ActionFn(285); - let __sym0 = __pop_Variant82(__symbols); + // TypeParams? = TypeParams => ActionFn(286); + let __sym0 = __pop_Variant91(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action285::<>(mode, __sym0); + let __nt = super::__action286::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant92(__nt), __end)); - (1, 262) + (1, 265) } - pub(crate) fn __reduce879< + pub(crate) fn __reduce884< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30030,14 +30136,14 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypeParamList? = => ActionFn(286); + // TypeParams? = => ActionFn(287); let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); let __end = __start.clone(); - let __nt = super::__action286::<>(mode, &__start, &__end); + let __nt = super::__action287::<>(mode, &__start, &__end); __symbols.push((__start, __Symbol::Variant92(__nt), __end)); - (0, 262) + (0, 265) } - pub(crate) fn __reduce880< + pub(crate) fn __reduce885< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30045,18 +30151,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypedParameter = Identifier, ":", Test<"all"> => ActionFn(1467); + // TypedParameter = Identifier, ":", Test<"all"> => ActionFn(1474); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant24(__symbols); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1467::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (3, 263) + let __nt = super::__action1474::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (3, 266) } - pub(crate) fn __reduce881< + pub(crate) fn __reduce886< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30064,15 +30170,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // TypedParameter = Identifier => ActionFn(1468); - let __sym0 = __pop_Variant24(__symbols); + // TypedParameter = Identifier => ActionFn(1475); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1468::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (1, 263) + let __nt = super::__action1475::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (1, 266) } - pub(crate) fn __reduce882< + pub(crate) fn __reduce887< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30080,15 +30186,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // UnaryOp = "+" => ActionFn(201); + // UnaryOp = "+" => ActionFn(205); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action201::<>(mode, __sym0); + let __nt = super::__action205::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant93(__nt), __end)); - (1, 264) + (1, 267) } - pub(crate) fn __reduce883< + pub(crate) fn __reduce888< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30096,15 +30202,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // UnaryOp = "-" => ActionFn(202); + // UnaryOp = "-" => ActionFn(206); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action202::<>(mode, __sym0); + let __nt = super::__action206::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant93(__nt), __end)); - (1, 264) + (1, 267) } - pub(crate) fn __reduce884< + pub(crate) fn __reduce889< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30112,15 +30218,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // UnaryOp = "~" => ActionFn(203); + // UnaryOp = "~" => ActionFn(207); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action203::<>(mode, __sym0); + let __nt = super::__action207::<>(mode, __sym0); __symbols.push((__start, __Symbol::Variant93(__nt), __end)); - (1, 264) + (1, 267) } - pub(crate) fn __reduce885< + pub(crate) fn __reduce890< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30128,15 +30234,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // UntypedParameter = Identifier => ActionFn(1469); - let __sym0 = __pop_Variant24(__symbols); + // UntypedParameter = Identifier => ActionFn(1476); + let __sym0 = __pop_Variant22(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1469::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant12(__nt), __end)); - (1, 265) + let __nt = super::__action1476::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (1, 268) } - pub(crate) fn __reduce886< + pub(crate) fn __reduce891< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30144,15 +30250,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // ValuePattern = MatchNameOrAttr => ActionFn(1470); - let __sym0 = __pop_Variant16(__symbols); + // ValuePattern = MatchNameOrAttr => ActionFn(1477); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1470::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant36(__nt), __end)); - (1, 266) + let __nt = super::__action1477::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant34(__nt), __end)); + (1, 269) } - pub(crate) fn __reduce887< + pub(crate) fn __reduce892< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30160,22 +30266,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WhileStatement = "while", NamedExpressionTest, ":", Suite, "else", ":", Suite => ActionFn(1111); + // WhileStatement = "while", NamedExpressionTest, ":", Suite, "else", ":", Suite => ActionFn(1115); assert!(__symbols.len() >= 7); - let __sym6 = __pop_Variant26(__symbols); + let __sym6 = __pop_Variant24(__symbols); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1111::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (7, 267) + let __nt = super::__action1115::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (7, 270) } - pub(crate) fn __reduce888< + pub(crate) fn __reduce893< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30183,19 +30289,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WhileStatement = "while", NamedExpressionTest, ":", Suite => ActionFn(1112); + // WhileStatement = "while", NamedExpressionTest, ":", Suite => ActionFn(1116); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1112::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 267) + let __nt = super::__action1116::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 270) } - pub(crate) fn __reduce889< + pub(crate) fn __reduce894< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30203,15 +30309,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItem<"all"> = Test<"all"> => ActionFn(1471); - let __sym0 = __pop_Variant16(__symbols); + // WithItem<"all"> = Test<"all"> => ActionFn(1478); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1471::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); - (1, 268) + let __nt = super::__action1478::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (1, 271) } - pub(crate) fn __reduce890< + pub(crate) fn __reduce895< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30219,18 +30325,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItem<"all"> = Test<"all">, "as", Expression<"all"> => ActionFn(1472); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // WithItem<"all"> = WithItemAs => ActionFn(300); + let __sym0 = __pop_Variant17(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1472::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); - (3, 268) + let __end = __sym0.2; + let __nt = super::__action300::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (1, 271) } - pub(crate) fn __reduce891< + pub(crate) fn __reduce896< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30238,18 +30341,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItem<"as"> = Test<"all">, "as", Expression<"all"> => ActionFn(1473); - assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); - let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + // WithItem<"no-withitems"> = Test<"no-withitems"> => ActionFn(1479); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; - let __end = __sym2.2; - let __nt = super::__action1473::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); - (3, 269) + let __end = __sym0.2; + let __nt = super::__action1479::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (1, 272) } - pub(crate) fn __reduce892< + pub(crate) fn __reduce897< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30257,15 +30357,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItem<"no-withitems"> = Test<"no-withitems"> => ActionFn(1474); - let __sym0 = __pop_Variant16(__symbols); + // WithItem<"no-withitems"> = WithItemAs => ActionFn(295); + let __sym0 = __pop_Variant17(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1474::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); - (1, 270) + let __nt = super::__action295::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (1, 272) } - pub(crate) fn __reduce893< + pub(crate) fn __reduce898< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30273,18 +30373,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItem<"no-withitems"> = Test<"all">, "as", Expression<"all"> => ActionFn(1475); + // WithItemAs = Test<"all">, "as", Expression<"all"> => ActionFn(1480); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1475::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant19(__nt), __end)); - (3, 270) + let __nt = super::__action1480::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant17(__nt), __end)); + (3, 273) } - pub(crate) fn __reduce894< + pub(crate) fn __reduce899< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30292,19 +30392,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ",", ")" => ActionFn(1482); + // WithItems = "(", OneOrMore>, ",", ")" => ActionFn(1487); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1482::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (4, 271) + let __nt = super::__action1487::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (4, 274) } - pub(crate) fn __reduce895< + pub(crate) fn __reduce900< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30312,18 +30412,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ")" => ActionFn(1483); + // WithItems = "(", OneOrMore>, ")" => ActionFn(1488); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1483::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (3, 271) + let __nt = super::__action1488::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (3, 274) } - pub(crate) fn __reduce896< + pub(crate) fn __reduce901< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30331,21 +30431,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ",", WithItem<"as">, ",", ")" => ActionFn(1485); + // WithItems = "(", OneOrMore>, ",", WithItemAs, ",", ")" => ActionFn(1490); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant19(__symbols); + let __sym3 = __pop_Variant17(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1485::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (6, 271) + let __nt = super::__action1490::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (6, 274) } - pub(crate) fn __reduce897< + pub(crate) fn __reduce902< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30353,19 +30453,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", WithItem<"as">, ",", ")" => ActionFn(1486); + // WithItems = "(", WithItemAs, ",", ")" => ActionFn(1491); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant19(__symbols); + let __sym1 = __pop_Variant17(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1486::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (4, 271) + let __nt = super::__action1491::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (4, 274) } - pub(crate) fn __reduce898< + pub(crate) fn __reduce903< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30373,22 +30473,22 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ",", WithItem<"as">, ("," >)+, ",", ")" => ActionFn(1487); + // WithItems = "(", OneOrMore>, ",", WithItemAs, ("," >)+, ",", ")" => ActionFn(1492); assert!(__symbols.len() >= 7); let __sym6 = __pop_Variant0(__symbols); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant20(__symbols); - let __sym3 = __pop_Variant19(__symbols); + let __sym4 = __pop_Variant18(__symbols); + let __sym3 = __pop_Variant17(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym6.2; - let __nt = super::__action1487::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (7, 271) + let __nt = super::__action1492::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (7, 274) } - pub(crate) fn __reduce899< + pub(crate) fn __reduce904< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30396,20 +30496,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", WithItem<"as">, ("," >)+, ",", ")" => ActionFn(1488); + // WithItems = "(", WithItemAs, ("," >)+, ",", ")" => ActionFn(1493); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant20(__symbols); - let __sym1 = __pop_Variant19(__symbols); + let __sym2 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant17(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1488::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (5, 271) + let __nt = super::__action1493::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (5, 274) } - pub(crate) fn __reduce900< + pub(crate) fn __reduce905< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30417,20 +30517,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ",", WithItem<"as">, ")" => ActionFn(1489); + // WithItems = "(", OneOrMore>, ",", WithItemAs, ")" => ActionFn(1494); assert!(__symbols.len() >= 5); let __sym4 = __pop_Variant0(__symbols); - let __sym3 = __pop_Variant19(__symbols); + let __sym3 = __pop_Variant17(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action1489::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (5, 271) + let __nt = super::__action1494::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (5, 274) } - pub(crate) fn __reduce901< + pub(crate) fn __reduce906< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30438,18 +30538,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", WithItem<"as">, ")" => ActionFn(1490); + // WithItems = "(", WithItemAs, ")" => ActionFn(1495); assert!(__symbols.len() >= 3); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant19(__symbols); + let __sym1 = __pop_Variant17(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1490::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (3, 271) + let __nt = super::__action1495::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (3, 274) } - pub(crate) fn __reduce902< + pub(crate) fn __reduce907< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30457,21 +30557,21 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", OneOrMore>, ",", WithItem<"as">, ("," >)+, ")" => ActionFn(1491); + // WithItems = "(", OneOrMore>, ",", WithItemAs, ("," >)+, ")" => ActionFn(1496); assert!(__symbols.len() >= 6); let __sym5 = __pop_Variant0(__symbols); - let __sym4 = __pop_Variant20(__symbols); - let __sym3 = __pop_Variant19(__symbols); + let __sym4 = __pop_Variant18(__symbols); + let __sym3 = __pop_Variant17(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant34(__symbols); + let __sym1 = __pop_Variant32(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym5.2; - let __nt = super::__action1491::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (6, 271) + let __nt = super::__action1496::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (6, 274) } - pub(crate) fn __reduce903< + pub(crate) fn __reduce908< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30479,19 +30579,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = "(", WithItem<"as">, ("," >)+, ")" => ActionFn(1492); + // WithItems = "(", WithItemAs, ("," >)+, ")" => ActionFn(1497); assert!(__symbols.len() >= 4); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant20(__symbols); - let __sym1 = __pop_Variant19(__symbols); + let __sym2 = __pop_Variant18(__symbols); + let __sym1 = __pop_Variant17(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action1492::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (4, 271) + let __nt = super::__action1497::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (4, 274) } - pub(crate) fn __reduce904< + pub(crate) fn __reduce909< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30499,15 +30599,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = WithItem<"no-withitems"> => ActionFn(158); - let __sym0 = __pop_Variant19(__symbols); + // WithItems = WithItem<"no-withitems"> => ActionFn(160); + let __sym0 = __pop_Variant17(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action158::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (1, 271) + let __nt = super::__action160::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (1, 274) } - pub(crate) fn __reduce905< + pub(crate) fn __reduce910< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30515,17 +30615,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItems = WithItem<"all">, ("," >)+ => ActionFn(159); + // WithItems = WithItem<"all">, ("," >)+ => ActionFn(161); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant20(__symbols); - let __sym0 = __pop_Variant19(__symbols); + let __sym1 = __pop_Variant18(__symbols); + let __sym0 = __pop_Variant17(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action159::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (2, 271) + let __nt = super::__action161::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (2, 274) } - pub(crate) fn __reduce906< + pub(crate) fn __reduce911< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30533,15 +30633,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithItemsNoAs = OneOrMore> => ActionFn(1476); - let __sym0 = __pop_Variant34(__symbols); + // WithItemsNoAs = OneOrMore> => ActionFn(1481); + let __sym0 = __pop_Variant32(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1476::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant41(__nt), __end)); - (1, 272) + let __nt = super::__action1481::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant39(__nt), __end)); + (1, 275) } - pub(crate) fn __reduce907< + pub(crate) fn __reduce912< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30549,20 +30649,20 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithStatement = "async", "with", WithItems, ":", Suite => ActionFn(941); + // WithStatement = "async", "with", WithItems, ":", Suite => ActionFn(943); assert!(__symbols.len() >= 5); - let __sym4 = __pop_Variant26(__symbols); + let __sym4 = __pop_Variant24(__symbols); let __sym3 = __pop_Variant0(__symbols); - let __sym2 = __pop_Variant41(__symbols); + let __sym2 = __pop_Variant39(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym4.2; - let __nt = super::__action941::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (5, 273) + let __nt = super::__action943::<>(mode, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (5, 276) } - pub(crate) fn __reduce908< + pub(crate) fn __reduce913< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30570,19 +30670,19 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // WithStatement = "with", WithItems, ":", Suite => ActionFn(942); + // WithStatement = "with", WithItems, ":", Suite => ActionFn(944); assert!(__symbols.len() >= 4); - let __sym3 = __pop_Variant26(__symbols); + let __sym3 = __pop_Variant24(__symbols); let __sym2 = __pop_Variant0(__symbols); - let __sym1 = __pop_Variant41(__symbols); + let __sym1 = __pop_Variant39(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym3.2; - let __nt = super::__action942::<>(mode, __sym0, __sym1, __sym2, __sym3); - __symbols.push((__start, __Symbol::Variant38(__nt), __end)); - (4, 273) + let __nt = super::__action944::<>(mode, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant36(__nt), __end)); + (4, 276) } - pub(crate) fn __reduce909< + pub(crate) fn __reduce914< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30590,18 +30690,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // XorExpression<"all"> = XorExpression<"all">, "^", AndExpression<"all"> => ActionFn(1477); + // XorExpression<"all"> = XorExpression<"all">, "^", AndExpression<"all"> => ActionFn(1482); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1477::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 274) + let __nt = super::__action1482::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 277) } - pub(crate) fn __reduce910< + pub(crate) fn __reduce915< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30609,15 +30709,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // XorExpression<"all"> = AndExpression<"all"> => ActionFn(428); - let __sym0 = __pop_Variant16(__symbols); + // XorExpression<"all"> = AndExpression<"all"> => ActionFn(406); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action428::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 274) + let __nt = super::__action406::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 277) } - pub(crate) fn __reduce911< + pub(crate) fn __reduce916< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30625,18 +30725,18 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // XorExpression<"no-withitems"> = XorExpression<"all">, "^", AndExpression<"all"> => ActionFn(1478); + // XorExpression<"no-withitems"> = XorExpression<"all">, "^", AndExpression<"all"> => ActionFn(1483); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); - let __sym0 = __pop_Variant16(__symbols); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1478::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 275) + let __nt = super::__action1483::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 278) } - pub(crate) fn __reduce912< + pub(crate) fn __reduce917< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30644,15 +30744,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // XorExpression<"no-withitems"> = AndExpression<"no-withitems"> => ActionFn(504); - let __sym0 = __pop_Variant16(__symbols); + // XorExpression<"no-withitems"> = AndExpression<"no-withitems"> => ActionFn(511); + let __sym0 = __pop_Variant14(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action504::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 275) + let __nt = super::__action511::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 278) } - pub(crate) fn __reduce913< + pub(crate) fn __reduce918< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30660,17 +30760,17 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // YieldExpr = "yield", GenericList => ActionFn(1708); + // YieldExpr = "yield", GenericList => ActionFn(1715); assert!(__symbols.len() >= 2); - let __sym1 = __pop_Variant16(__symbols); + let __sym1 = __pop_Variant14(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym1.2; - let __nt = super::__action1708::<>(mode, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (2, 276) + let __nt = super::__action1715::<>(mode, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (2, 279) } - pub(crate) fn __reduce914< + pub(crate) fn __reduce919< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30678,15 +30778,15 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // YieldExpr = "yield" => ActionFn(1709); + // YieldExpr = "yield" => ActionFn(1716); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym0.2; - let __nt = super::__action1709::<>(mode, __sym0); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (1, 276) + let __nt = super::__action1716::<>(mode, __sym0); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (1, 279) } - pub(crate) fn __reduce915< + pub(crate) fn __reduce920< >( mode: Mode, __lookahead_start: Option<&TextSize>, @@ -30694,16 +30794,16 @@ mod __parse__Top { _: core::marker::PhantomData<()>, ) -> (usize, usize) { - // YieldExpr = "yield", "from", Test<"all"> => ActionFn(1480); + // YieldExpr = "yield", "from", Test<"all"> => ActionFn(1485); assert!(__symbols.len() >= 3); - let __sym2 = __pop_Variant16(__symbols); + let __sym2 = __pop_Variant14(__symbols); let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant0(__symbols); let __start = __sym0.0; let __end = __sym2.2; - let __nt = super::__action1480::<>(mode, __sym0, __sym1, __sym2); - __symbols.push((__start, __Symbol::Variant16(__nt), __end)); - (3, 276) + let __nt = super::__action1485::<>(mode, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant14(__nt), __end)); + (3, 279) } } pub(crate) use self::__parse__Top::TopParser; @@ -31012,6 +31112,17 @@ fn __action22< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action23< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Stmt, TextSize), +) -> ast::Stmt +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action24< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31026,7 +31137,7 @@ fn __action23< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action24< +fn __action25< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31044,7 +31155,7 @@ fn __action24< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action25< +fn __action26< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31078,7 +31189,7 @@ fn __action25< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action26< +fn __action27< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31102,7 +31213,7 @@ fn __action26< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action27< +fn __action28< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31129,7 +31240,7 @@ fn __action27< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action28< +fn __action29< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -31141,7 +31252,7 @@ fn __action28< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action29< +fn __action30< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -31153,7 +31264,7 @@ fn __action29< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action30< +fn __action31< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31164,7 +31275,7 @@ fn __action30< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action31< +fn __action32< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31175,7 +31286,7 @@ fn __action31< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action32< +fn __action33< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31186,7 +31297,7 @@ fn __action32< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action33< +fn __action34< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31197,7 +31308,7 @@ fn __action33< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action34< +fn __action35< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31208,7 +31319,7 @@ fn __action34< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action35< +fn __action36< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31219,7 +31330,7 @@ fn __action35< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action36< +fn __action37< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31230,7 +31341,7 @@ fn __action36< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action37< +fn __action38< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31241,7 +31352,7 @@ fn __action37< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action38< +fn __action39< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -31252,7 +31363,7 @@ fn __action38< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action39< +fn __action40< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31263,7 +31374,7 @@ fn __action39< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action40< +fn __action41< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31274,7 +31385,7 @@ fn __action40< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action41< +fn __action42< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31285,7 +31396,7 @@ fn __action41< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action42< +fn __action43< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31296,7 +31407,7 @@ fn __action42< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action43< +fn __action44< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31307,7 +31418,7 @@ fn __action43< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action44< +fn __action45< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31318,7 +31429,7 @@ fn __action44< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action45< +fn __action46< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31329,7 +31440,7 @@ fn __action45< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action46< +fn __action47< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31340,7 +31451,7 @@ fn __action46< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action47< +fn __action48< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31351,7 +31462,7 @@ fn __action47< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action48< +fn __action49< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31362,7 +31473,7 @@ fn __action48< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action49< +fn __action50< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31373,7 +31484,7 @@ fn __action49< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action50< +fn __action51< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31384,7 +31495,7 @@ fn __action50< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action51< +fn __action52< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31395,7 +31506,7 @@ fn __action51< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action52< +fn __action53< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31411,7 +31522,7 @@ fn __action52< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action53< +fn __action54< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31426,7 +31537,7 @@ fn __action53< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action54< +fn __action55< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31444,7 +31555,7 @@ fn __action54< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action55< +fn __action56< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31461,7 +31572,7 @@ fn __action55< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action56< +fn __action57< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31472,7 +31583,7 @@ fn __action56< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action57< +fn __action58< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31489,7 +31600,7 @@ fn __action57< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action58< +fn __action59< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31508,7 +31619,7 @@ fn __action58< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action59< +fn __action60< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31526,7 +31637,7 @@ fn __action59< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action60< +fn __action61< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31552,7 +31663,7 @@ fn __action60< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action61< +fn __action62< >( mode: Mode, (_, dots, _): (TextSize, alloc::vec::Vec, TextSize), @@ -31566,7 +31677,7 @@ fn __action61< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action62< +fn __action63< >( mode: Mode, (_, dots, _): (TextSize, alloc::vec::Vec, TextSize), @@ -31579,7 +31690,7 @@ fn __action62< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action63< +fn __action64< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31590,7 +31701,7 @@ fn __action63< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action64< +fn __action65< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -31601,7 +31712,7 @@ fn __action64< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action65< +fn __action66< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31614,7 +31725,7 @@ fn __action65< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action66< +fn __action67< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31630,7 +31741,7 @@ fn __action66< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action67< +fn __action68< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31646,7 +31757,7 @@ fn __action67< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action68< +fn __action69< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31659,7 +31770,7 @@ fn __action68< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action69< +fn __action70< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31680,7 +31791,7 @@ fn __action69< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action70< +fn __action71< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31698,7 +31809,7 @@ fn __action70< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action71< +fn __action72< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31716,7 +31827,7 @@ fn __action71< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action72< +fn __action73< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31739,26 +31850,26 @@ fn __action72< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action73< +fn __action74< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, m, _): (TextSize, (MagicKind, String), TextSize), + (_, c, _): (TextSize, (IpyEscapeKind, String), TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> Result> { { if mode == Mode::Jupyter { - Ok(ast::Stmt::LineMagic( - ast::StmtLineMagic { - kind: m.0, - value: m.1, + Ok(ast::Stmt::IpyEscapeCommand( + ast::StmtIpyEscapeCommand { + kind: c.0, + value: c.1, range: (location..end_location).into() } )) } else { Err(LexicalError { - error: LexicalErrorType::OtherError("line magics are only allowed in Jupyter mode".to_string()), + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), location, })? } @@ -31767,33 +31878,33 @@ fn __action73< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action74< +fn __action75< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, m, _): (TextSize, (MagicKind, String), TextSize), + (_, c, _): (TextSize, (IpyEscapeKind, String), TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> Result> { { if mode == Mode::Jupyter { // This should never occur as the lexer won't allow it. - if !matches!(m.0, MagicKind::Magic | MagicKind::Shell) { + if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) { return Err(LexicalError { - error: LexicalErrorType::OtherError("expr line magics are only allowed for % and !".to_string()), + error: LexicalErrorType::OtherError("IPython escape command expr is only allowed for % and !".to_string()), location, })?; } - Ok(ast::Expr::LineMagic( - ast::ExprLineMagic { - kind: m.0, - value: m.1, + Ok(ast::Expr::IpyEscapeCommand( + ast::ExprIpyEscapeCommand { + kind: c.0, + value: c.1, range: (location..end_location).into() } )) } else { Err(LexicalError { - error: LexicalErrorType::OtherError("line magics are only allowed in Jupyter mode".to_string()), + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), location, })? } @@ -31802,7 +31913,86 @@ fn __action74< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action75< +fn __action76< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), + (_, suffix, _): (TextSize, alloc::vec::Vec, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> Result> +{ + { + fn unparse_expr(expr: &ast::Expr, buffer: &mut String) -> Result<(), LexicalError> { + match expr { + ast::Expr::Name(ast::ExprName { id, .. }) => { + buffer.push_str(id.as_str()); + }, + ast::Expr::Subscript(ast::ExprSubscript { value, slice, range, .. }) => { + let ast::Expr::Constant(ast::ExprConstant { value: ast::Constant::Int(integer), .. }) = slice.as_ref() else { + return Err(LexicalError { + error: LexicalErrorType::OtherError("only integer constants are allowed in Subscript expressions in help end escape command".to_string()), + location: range.start(), + }); + }; + unparse_expr(value, buffer)?; + buffer.push('['); + buffer.push_str(&format!("{}", integer)); + buffer.push(']'); + }, + ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { + unparse_expr(value, buffer)?; + buffer.push('.'); + buffer.push_str(attr.as_str()); + }, + _ => { + return Err(LexicalError { + error: LexicalErrorType::OtherError("only Name, Subscript and Attribute expressions are allowed in help end escape command".to_string()), + location: expr.range().start(), + }); + } + } + Ok(()) + } + + if mode != Mode::Jupyter { + return Err(ParseError::User { + error: LexicalError { + error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), + location, + }, + }); + } + + let kind = match suffix.len() { + 1 => IpyEscapeKind::Help, + 2 => IpyEscapeKind::Help2, + _ => { + return Err(ParseError::User { + error: LexicalError { + error: LexicalErrorType::OtherError("maximum of 2 `?` tokens are allowed in help end escape command".to_string()), + location, + }, + }); + } + }; + + let mut value = String::new(); + unparse_expr(&e, &mut value)?; + + Ok(ast::Stmt::IpyEscapeCommand( + ast::StmtIpyEscapeCommand { + kind, + value, + range: (location..end_location).into() + } + )) + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action77< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31813,7 +32003,7 @@ fn __action75< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action76< +fn __action78< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31824,7 +32014,7 @@ fn __action76< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action77< +fn __action79< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31835,7 +32025,7 @@ fn __action77< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action78< +fn __action80< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31846,7 +32036,7 @@ fn __action78< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action79< +fn __action81< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31857,7 +32047,7 @@ fn __action79< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action80< +fn __action82< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31868,7 +32058,7 @@ fn __action80< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action81< +fn __action83< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31879,7 +32069,7 @@ fn __action81< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action82< +fn __action84< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -31890,7 +32080,7 @@ fn __action82< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action83< +fn __action85< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31923,7 +32113,7 @@ fn __action83< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action84< +fn __action86< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31957,7 +32147,7 @@ fn __action84< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action85< +fn __action87< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -31997,7 +32187,7 @@ fn __action85< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action86< +fn __action88< >( mode: Mode, (_, start, _): (TextSize, TextSize, TextSize), @@ -32022,7 +32212,7 @@ fn __action86< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action87< +fn __action89< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -32036,7 +32226,7 @@ fn __action87< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action88< +fn __action90< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32055,7 +32245,7 @@ fn __action88< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action89< +fn __action91< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32076,7 +32266,7 @@ fn __action89< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action90< +fn __action92< >( mode: Mode, (_, pattern, _): (TextSize, ast::Pattern, TextSize), @@ -32087,7 +32277,7 @@ fn __action90< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action91< +fn __action93< >( mode: Mode, (_, pattern, _): (TextSize, ast::Pattern, TextSize), @@ -32098,7 +32288,7 @@ fn __action91< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action92< +fn __action94< >( mode: Mode, (_, pattern, _): (TextSize, ast::Pattern, TextSize), @@ -32109,7 +32299,7 @@ fn __action92< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action93< +fn __action95< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32139,7 +32329,7 @@ fn __action93< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action94< +fn __action96< >( mode: Mode, (_, pattern, _): (TextSize, ast::Pattern, TextSize), @@ -32150,7 +32340,7 @@ fn __action94< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action95< +fn __action97< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32167,7 +32357,7 @@ fn __action95< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action96< +fn __action98< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32178,7 +32368,7 @@ fn __action96< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action97< +fn __action99< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32189,7 +32379,7 @@ fn __action97< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action98< +fn __action100< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32200,7 +32390,7 @@ fn __action98< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action99< +fn __action101< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32211,7 +32401,7 @@ fn __action99< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action100< +fn __action102< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32222,7 +32412,7 @@ fn __action100< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action101< +fn __action103< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32233,7 +32423,7 @@ fn __action101< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action102< +fn __action104< >( mode: Mode, (_, node, _): (TextSize, ast::Pattern, TextSize), @@ -32244,7 +32434,7 @@ fn __action102< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action103< +fn __action105< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32259,7 +32449,7 @@ fn __action103< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action104< +fn __action106< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32276,7 +32466,7 @@ fn __action104< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action105< +fn __action107< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32297,7 +32487,7 @@ fn __action105< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action106< +fn __action108< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32321,7 +32511,7 @@ fn __action106< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action107< +fn __action109< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32339,7 +32529,7 @@ fn __action107< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action108< +fn __action110< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32356,7 +32546,7 @@ fn __action108< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action109< +fn __action111< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32371,7 +32561,7 @@ fn __action109< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action110< +fn __action112< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -32382,7 +32572,7 @@ fn __action110< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action111< +fn __action113< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32402,7 +32592,7 @@ fn __action111< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action112< +fn __action114< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32424,7 +32614,7 @@ fn __action112< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action113< +fn __action115< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32440,7 +32630,7 @@ fn __action113< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action114< +fn __action116< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32456,7 +32646,7 @@ fn __action114< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action115< +fn __action117< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32472,7 +32662,7 @@ fn __action115< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action116< +fn __action118< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32488,7 +32678,7 @@ fn __action116< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action117< +fn __action119< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32504,7 +32694,7 @@ fn __action117< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action118< +fn __action120< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32520,7 +32710,7 @@ fn __action118< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action119< +fn __action121< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32537,7 +32727,7 @@ fn __action119< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action120< +fn __action122< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32552,7 +32742,7 @@ fn __action120< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action121< +fn __action123< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32574,7 +32764,7 @@ fn __action121< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action122< +fn __action124< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32596,7 +32786,7 @@ fn __action122< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action123< +fn __action125< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32612,7 +32802,7 @@ fn __action123< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action124< +fn __action126< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -32623,7 +32813,7 @@ fn __action124< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action125< +fn __action127< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -32634,7 +32824,7 @@ fn __action125< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action126< +fn __action128< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -32645,7 +32835,7 @@ fn __action126< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action127< +fn __action129< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32664,7 +32854,7 @@ fn __action127< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action128< +fn __action130< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32683,7 +32873,7 @@ fn __action128< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action129< +fn __action131< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32702,7 +32892,7 @@ fn __action129< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action130< +fn __action132< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32714,7 +32904,7 @@ fn __action130< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action131< +fn __action133< >( mode: Mode, (_, k, _): (TextSize, ast::Expr, TextSize), @@ -32727,7 +32917,7 @@ fn __action131< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action132< +fn __action134< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32748,7 +32938,7 @@ fn __action132< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action133< +fn __action135< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32774,7 +32964,7 @@ fn __action133< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action134< +fn __action136< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32798,7 +32988,7 @@ fn __action134< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action135< +fn __action137< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32827,7 +33017,7 @@ fn __action135< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action136< +fn __action138< >( mode: Mode, (_, k, _): (TextSize, ast::Identifier, TextSize), @@ -32840,7 +33030,7 @@ fn __action136< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action137< +fn __action139< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32870,7 +33060,7 @@ fn __action137< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action138< +fn __action140< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32895,7 +33085,7 @@ fn __action138< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action139< +fn __action141< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32923,7 +33113,7 @@ fn __action139< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action140< +fn __action142< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32946,7 +33136,7 @@ fn __action140< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action141< +fn __action143< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -32976,7 +33166,7 @@ fn __action141< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action142< +fn __action144< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33001,7 +33191,7 @@ fn __action142< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action143< +fn __action145< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33029,7 +33219,7 @@ fn __action143< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action144< +fn __action146< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33052,7 +33242,7 @@ fn __action144< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action145< +fn __action147< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33087,7 +33277,7 @@ fn __action145< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action146< +fn __action148< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33118,7 +33308,7 @@ fn __action146< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action147< +fn __action149< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33141,17 +33331,13 @@ fn __action147< .end(); let target = Box::new(set_context(target, ast::ExprContext::Store)); let iter = Box::new(iter); - if is_async.is_some() { - ast::Stmt::AsyncFor(ast::StmtAsyncFor { target, iter, body, orelse, range: (location..end_location).into() }) - } else { - ast::Stmt::For(ast::StmtFor { target, iter, body, orelse, range: (location..end_location).into() }) - } + ast::Stmt::For(ast::StmtFor { target, iter, body, orelse, is_async: is_async.is_some(), range: (location..end_location).into() }) } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action148< +fn __action150< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33179,6 +33365,7 @@ fn __action148< handlers, orelse, finalbody, + is_star: false, range: (location..end_location).into() }, ) @@ -33187,7 +33374,7 @@ fn __action148< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action149< +fn __action151< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33209,12 +33396,13 @@ fn __action149< .map(Ranged::end) .or_else(|| handlers.last().map(Ranged::end)) .unwrap(); - ast::Stmt::TryStar( - ast::StmtTryStar { + ast::Stmt::Try( + ast::StmtTry { body, handlers, orelse, finalbody, + is_star: true, range: (location..end_location).into() }, ) @@ -33223,7 +33411,7 @@ fn __action149< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action150< +fn __action152< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33243,6 +33431,7 @@ fn __action150< handlers, orelse, finalbody, + is_star: false, range: (location..end_location).into() }, ) @@ -33251,7 +33440,7 @@ fn __action150< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action151< +fn __action153< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33277,7 +33466,7 @@ fn __action151< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action152< +fn __action154< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33303,7 +33492,7 @@ fn __action152< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action153< +fn __action155< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33328,7 +33517,7 @@ fn __action153< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action154< +fn __action156< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33353,7 +33542,7 @@ fn __action154< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action155< +fn __action157< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33366,17 +33555,13 @@ fn __action155< { { let end_location = body.last().unwrap().end(); - if is_async.is_some() { - ast::StmtAsyncWith { items, body, range: (location..end_location).into() }.into() - } else { - ast::StmtWith { items, body, range: (location..end_location).into() }.into() - } + ast::StmtWith { items, body, is_async: is_async.is_some(), range: (location..end_location).into() }.into() } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action156< +fn __action158< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -33390,7 +33575,7 @@ fn __action156< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action157< +fn __action159< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -33408,7 +33593,7 @@ fn __action157< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action158< +fn __action160< >( mode: Mode, (_, __0, _): (TextSize, ast::WithItem, TextSize), @@ -33419,7 +33604,7 @@ fn __action158< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action159< +fn __action161< >( mode: Mode, (_, item, _): (TextSize, ast::WithItem, TextSize), @@ -33433,7 +33618,7 @@ fn __action159< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action160< +fn __action162< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33448,7 +33633,25 @@ fn __action160< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action161< +fn __action163< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, context_expr, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, vars, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::WithItem +{ + { + let optional_vars = Some(Box::new(set_context(vars, ast::ExprContext::Store))); + ast::WithItem { context_expr, optional_vars, range: (location..end_location).into() } + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action164< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33456,8 +33659,8 @@ fn __action161< (_, is_async, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, name, _): (TextSize, ast::Identifier, TextSize), - (_, type_params, _): (TextSize, core::option::Option>, TextSize), - (_, args, _): (TextSize, ast::Arguments, TextSize), + (_, type_params, _): (TextSize, core::option::Option, TextSize), + (_, args, _): (TextSize, ast::Parameters, TextSize), (_, r, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, body, _): (TextSize, ast::Suite, TextSize), @@ -33467,17 +33670,13 @@ fn __action161< let args = Box::new(args); let returns = r.map(Box::new); let end_location = body.last().unwrap().end(); - if is_async.is_some() { - ast::StmtAsyncFunctionDef { name, args, body, decorator_list, returns, type_params: type_params.unwrap_or_default(), range: (location..end_location).into() }.into() - } else { - ast::StmtFunctionDef { name, args, body, decorator_list, returns, type_params: type_params.unwrap_or_default(), range: (location..end_location).into() }.into() - } + ast::StmtFunctionDef { name, parameters:args, body, decorator_list, returns, type_params, is_async: is_async.is_some(), range: (location..end_location).into() }.into() } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action162< +fn __action165< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33492,13 +33691,13 @@ fn __action162< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action163< +fn __action166< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, name, _): (TextSize, ast::Expr, TextSize), - (_, type_params, _): (TextSize, core::option::Option>, TextSize), + (_, type_params, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, value, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), @@ -33509,7 +33708,7 @@ fn __action163< ast::StmtTypeAlias { name: Box::new(name), value: Box::new(value), - type_params: type_params.unwrap_or_default(), + type_params, range: (location..end_location).into() }, ) @@ -33518,22 +33717,22 @@ fn __action163< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action164< +fn __action167< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, a, _): (TextSize, core::option::Option, TextSize), + (_, a, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { { a.as_ref().map(validate_arguments).transpose()?; let range = (location..end_location).into(); let args = a - .map_or_else(|| ast::Arguments::empty(range), |mut arguments| { + .map_or_else(|| ast::Parameters::empty(range), |mut arguments| { arguments.range = range; arguments }); @@ -33544,114 +33743,109 @@ fn __action164< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action165< +fn __action168< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, arg, _): (TextSize, ast::Identifier, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { { - let def = ast::Arg { arg, annotation: None, range: (location..end_location).into() }; - ast::ArgWithDefault { def, default: None, range: (location..end_location).into() } + let def = ast::Parameter { name:arg, annotation: None, range: (location..end_location).into() }; + ast::ParameterWithDefault { parameter:def, default: None, range: (location..end_location).into() } } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action166< +fn __action169< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, arg, _): (TextSize, ast::Identifier, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { - ast::Arg { arg, annotation: None, range: (location..end_location).into() } + ast::Parameter { name:arg, annotation: None, range: (location..end_location).into() } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action167< +fn __action170< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, arg, _): (TextSize, ast::Identifier, TextSize), (_, a, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { { let annotation = a.map(Box::new); - let def = ast::Arg { arg, annotation, range: (location..end_location).into() }; - ast::ArgWithDefault { def, default: None, range: (location..end_location).into() } + let def = ast::Parameter { name:arg, annotation, range: (location..end_location).into() }; + ast::ParameterWithDefault { parameter:def, default: None, range: (location..end_location).into() } } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action168< +fn __action171< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, arg, _): (TextSize, ast::Identifier, TextSize), (_, a, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { { let annotation = a.map(Box::new); - ast::Arg { arg, annotation, range: (location..end_location).into() } + ast::Parameter { name:arg, annotation, range: (location..end_location).into() } } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action169< +fn __action172< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, arg, _): (TextSize, ast::Identifier, TextSize), (_, a, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { { let annotation = a.map(Box::new); - ast::Arg { arg, annotation, range: (location..end_location).into() } + ast::Parameter { name:arg, annotation, range: (location..end_location).into() } } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action170< +fn __action173< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, decorator_list, _): (TextSize, alloc::vec::Vec, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, name, _): (TextSize, ast::Identifier, TextSize), - (_, type_params, _): (TextSize, core::option::Option>, TextSize), - (_, a, _): (TextSize, core::option::Option<(token::Tok, ArgumentList, token::Tok)>, TextSize), + (_, type_params, _): (TextSize, core::option::Option, TextSize), + (_, arguments, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, body, _): (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { { - let (bases, keywords) = match a { - Some((_, arg, _)) => (arg.args, arg.keywords), - None => (vec![], vec![]), - }; let end_location = body.last().unwrap().end(); ast::Stmt::ClassDef( ast::StmtClassDef { name, - bases, - keywords, + arguments: arguments.map(Box::new), body, decorator_list, - type_params: type_params.unwrap_or_default(), + type_params: type_params.map(Box::new), range: (location..end_location).into() }, ) @@ -33660,7 +33854,7 @@ fn __action170< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action171< +fn __action174< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33669,16 +33863,19 @@ fn __action171< (_, _, _): (TextSize, core::option::Option, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Vec +) -> ast::TypeParams { { - vars + ast::TypeParams { + type_params: vars, + range: (location..end_location).into() + } } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action172< +fn __action175< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33696,7 +33893,7 @@ fn __action172< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action173< +fn __action176< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33714,7 +33911,7 @@ fn __action173< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action174< +fn __action177< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33732,7 +33929,7 @@ fn __action174< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action175< +fn __action178< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33749,7 +33946,7 @@ fn __action175< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action176< +fn __action179< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33765,7 +33962,7 @@ fn __action176< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action177< +fn __action180< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -33782,7 +33979,7 @@ fn __action177< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action178< +fn __action181< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -33793,7 +33990,7 @@ fn __action178< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action179< +fn __action182< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -33804,24 +34001,37 @@ fn __action179< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action180< +fn __action183< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, id, _): (TextSize, ast::Identifier, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + ast::Expr::Name( + ast::ExprName { id: id.into(), ctx: ast::ExprContext::Store, range: (location..end_location).into() }, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action184< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, target, _): (TextSize, ast::Expr, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, value, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { { ast::Expr::NamedExpr( ast::ExprNamedExpr { - target: Box::new(ast::Expr::Name( - ast::ExprName { id: id.into(), ctx: ast::ExprContext::Store, range: (location..end_location).into() }, - )), - range: (location..value.end()).into(), + target: Box::new(target), value: Box::new(value), + range: (location..end_location).into(), } ) } @@ -33829,13 +34039,13 @@ fn __action180< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action181< +fn __action185< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, location_args, _): (TextSize, TextSize, TextSize), - (_, p, _): (TextSize, core::option::Option, TextSize), + (_, parameters, _): (TextSize, core::option::Option, TextSize), (_, end_location_args, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, body, _): (TextSize, ast::Expr, TextSize), @@ -33843,13 +34053,11 @@ fn __action181< ) -> Result> { { - p.as_ref().map(validate_arguments).transpose()?; - let p = p - .unwrap_or_else(|| ast::Arguments::empty((location_args..end_location_args).into())); + parameters.as_ref().map(validate_arguments).transpose()?; Ok(ast::Expr::Lambda( ast::ExprLambda { - args: Box::new(p), + parameters: parameters.map(Box::new), body: Box::new(body), range: (location..end_location).into() } @@ -33859,7 +34067,7 @@ fn __action181< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action182< +fn __action186< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33870,7 +34078,7 @@ fn __action182< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action183< +fn __action187< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33881,7 +34089,7 @@ fn __action183< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action184< +fn __action188< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33892,7 +34100,7 @@ fn __action184< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action185< +fn __action189< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33903,7 +34111,7 @@ fn __action185< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action186< +fn __action190< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33914,7 +34122,7 @@ fn __action186< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action187< +fn __action191< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33925,7 +34133,7 @@ fn __action187< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action188< +fn __action192< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33936,7 +34144,7 @@ fn __action188< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action189< +fn __action193< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33948,7 +34156,7 @@ fn __action189< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action190< +fn __action194< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33959,7 +34167,7 @@ fn __action190< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action191< +fn __action195< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33971,7 +34179,7 @@ fn __action191< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action192< +fn __action196< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33982,7 +34190,7 @@ fn __action192< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action193< +fn __action197< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -33993,7 +34201,7 @@ fn __action193< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action194< +fn __action198< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34004,7 +34212,7 @@ fn __action194< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action195< +fn __action199< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34015,7 +34223,7 @@ fn __action195< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action196< +fn __action200< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34026,7 +34234,7 @@ fn __action196< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action197< +fn __action201< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34037,7 +34245,7 @@ fn __action197< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action198< +fn __action202< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34048,7 +34256,7 @@ fn __action198< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action199< +fn __action203< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34059,7 +34267,7 @@ fn __action199< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action200< +fn __action204< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34070,7 +34278,7 @@ fn __action200< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action201< +fn __action205< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34081,7 +34289,7 @@ fn __action201< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action202< +fn __action206< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34092,7 +34300,7 @@ fn __action202< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action203< +fn __action207< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -34103,7 +34311,7 @@ fn __action203< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action204< +fn __action208< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34118,7 +34326,7 @@ fn __action204< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action205< +fn __action209< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34136,7 +34344,7 @@ fn __action205< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action206< +fn __action210< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34154,7 +34362,7 @@ fn __action206< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action207< +fn __action211< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34165,7 +34373,7 @@ fn __action207< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action208< +fn __action212< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34188,7 +34396,7 @@ fn __action208< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action209< +fn __action213< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34201,7 +34409,7 @@ fn __action209< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action210< +fn __action214< >( mode: Mode, (_, e, _): (TextSize, Vec, TextSize), @@ -34213,7 +34421,7 @@ fn __action210< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action211< +fn __action215< >( mode: Mode, (_, elements, _): (TextSize, Vec<(Option>, ast::Expr)>, TextSize), @@ -34225,7 +34433,7 @@ fn __action211< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action212< +fn __action216< >( mode: Mode, (_, e1, _): (TextSize, ast::Expr, TextSize), @@ -34238,7 +34446,7 @@ fn __action212< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action213< +fn __action217< >( mode: Mode, (_, e, _): (TextSize, (ast::Expr, ast::Expr), TextSize), @@ -34249,7 +34457,7 @@ fn __action213< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action214< +fn __action218< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -34261,7 +34469,7 @@ fn __action214< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action215< +fn __action219< >( mode: Mode, (_, e1, _): (TextSize, Vec, TextSize), @@ -34273,7 +34481,7 @@ fn __action215< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action216< +fn __action220< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34284,7 +34492,7 @@ fn __action216< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action217< +fn __action221< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34295,7 +34503,7 @@ fn __action217< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action218< +fn __action222< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34306,7 +34514,7 @@ fn __action218< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action219< +fn __action223< >( mode: Mode, (_, elements, _): (TextSize, Vec, TextSize), @@ -34318,7 +34526,7 @@ fn __action219< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action220< +fn __action224< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34329,7 +34537,7 @@ fn __action220< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action221< +fn __action225< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34345,7 +34553,7 @@ fn __action221< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action222< +fn __action226< >( mode: Mode, (_, c, _): (TextSize, alloc::vec::Vec, TextSize), @@ -34356,7 +34564,7 @@ fn __action222< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action223< +fn __action227< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34383,7 +34591,7 @@ fn __action223< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action224< +fn __action228< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34394,7 +34602,7 @@ fn __action224< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action225< +fn __action229< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -34406,21 +34614,29 @@ fn __action225< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action226< +fn __action230< >( mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), (_, e, _): (TextSize, Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), -) -> Result> + (_, _, _): (TextSize, token::Tok, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> Result> { { - let arg_list = parse_args(e)?; - Ok(arg_list) + let ArgumentList { args, keywords } = parse_arguments(e)?; + Ok(ast::Arguments { + args, + keywords, + range: (location..end_location).into() + }) } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action227< +fn __action231< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34446,7 +34662,7 @@ fn __action227< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action228< +fn __action232< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34461,7 +34677,7 @@ fn __action228< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action229< +fn __action233< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34480,7 +34696,7 @@ fn __action229< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action230< +fn __action234< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34494,7 +34710,7 @@ fn __action230< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action231< +fn __action235< >( mode: Mode, (_, value, _): (TextSize, BigInt, TextSize), @@ -34505,7 +34721,7 @@ fn __action231< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action232< +fn __action236< >( mode: Mode, (_, value, _): (TextSize, f64, TextSize), @@ -34516,7 +34732,7 @@ fn __action232< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action233< +fn __action237< >( mode: Mode, (_, s, _): (TextSize, (f64, f64), TextSize), @@ -34527,7 +34743,7 @@ fn __action233< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action234< +fn __action238< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34540,7 +34756,7 @@ fn __action234< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action235< +fn __action239< >( mode: Mode, (_, __0, _): (TextSize, Vec, TextSize), @@ -34551,7 +34767,7 @@ fn __action235< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action236< +fn __action240< >( mode: Mode, __lookbehind: &TextSize, @@ -34563,7 +34779,7 @@ fn __action236< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action237< +fn __action241< >( mode: Mode, (_, mut v, _): (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -34580,7 +34796,7 @@ fn __action237< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action238< +fn __action242< >( mode: Mode, __lookbehind: &TextSize, @@ -34592,7 +34808,7 @@ fn __action238< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action239< +fn __action243< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -34603,7 +34819,7 @@ fn __action239< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action240< +fn __action244< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34622,7 +34838,7 @@ fn __action240< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action241< +fn __action245< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -34633,7 +34849,7 @@ fn __action241< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action242< +fn __action246< >( mode: Mode, (_, __0, _): (TextSize, ast::Comprehension, TextSize), @@ -34644,7 +34860,7 @@ fn __action242< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action243< +fn __action247< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -34656,7 +34872,7 @@ fn __action243< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action244< +fn __action248< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34678,7 +34894,7 @@ fn __action244< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action245< +fn __action249< >( mode: Mode, (_, e, _): (TextSize, ast::Expr, TextSize), @@ -34689,7 +34905,7 @@ fn __action245< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action246< +fn __action250< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -34705,7 +34921,7 @@ fn __action246< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action247< +fn __action251< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -34727,35 +34943,7 @@ fn __action247< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action248< ->( - mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitOr, right: Box::new(e2), range: (location..end_location).into() } - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action249< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr -{ - __0 -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action250< +fn __action252< >( mode: Mode, (_, e, _): (TextSize, (Option>, ast::Expr), TextSize), @@ -34766,7 +34954,7 @@ fn __action250< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action251< +fn __action253< >( mode: Mode, (_, mut v, _): (TextSize, Vec<(Option>, ast::Expr)>, TextSize), @@ -34782,7 +34970,7 @@ fn __action251< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action252< +fn __action254< >( mode: Mode, (_, e, _): (TextSize, ast::Expr, TextSize), @@ -34793,7 +34981,7 @@ fn __action252< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action253< +fn __action255< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -34809,7 +34997,7 @@ fn __action253< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action254< +fn __action256< >( mode: Mode, (_, __0, _): (TextSize, Option, TextSize), @@ -34820,7 +35008,7 @@ fn __action254< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action255< +fn __action257< >( mode: Mode, __lookbehind: &TextSize, @@ -34832,7 +35020,7 @@ fn __action255< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action256< +fn __action258< >( mode: Mode, (_, e1, _): (TextSize, ast::Expr, TextSize), @@ -34845,7 +35033,7 @@ fn __action256< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action257< +fn __action259< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -34861,38 +35049,38 @@ fn __action257< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action258< +fn __action260< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arguments, TextSize), -) -> core::option::Option + (_, __0, _): (TextSize, ast::Parameters, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action259< +fn __action261< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action260< +fn __action262< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, param1, _): (TextSize, (Vec, Vec), TextSize), - (_, args2, _): (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + (_, param1, _): (TextSize, (Vec, Vec), TextSize), + (_, args2, _): (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { { validate_pos_params(¶m1)?; @@ -34901,7 +35089,7 @@ fn __action260< // Now gather rest of parameters: let (vararg, kwonlyargs, kwarg) = args2.unwrap_or((None, vec![], None)); - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -34914,15 +35102,15 @@ fn __action260< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action261< +fn __action263< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, param1, _): (TextSize, (Vec, Vec), TextSize), - (_, kw, _): (TextSize, Option>, TextSize), + (_, param1, _): (TextSize, (Vec, Vec), TextSize), + (_, kw, _): (TextSize, Option>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { { validate_pos_params(¶m1)?; @@ -34933,7 +35121,7 @@ fn __action261< let kwonlyargs = vec![]; let kwarg = kw; - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -34946,18 +35134,18 @@ fn __action261< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action262< +fn __action264< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, params, _): (TextSize, (Option>, Vec, Option>), TextSize), + (_, params, _): (TextSize, (Option>, Vec, Option>), TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { { let (vararg, kwonlyargs, kwarg) = params; - ast::Arguments { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs, @@ -34970,17 +35158,17 @@ fn __action262< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action263< +fn __action265< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, kwarg, _): (TextSize, Option>, TextSize), + (_, kwarg, _): (TextSize, Option>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { { - ast::Arguments { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs: vec![], @@ -34993,7 +35181,7 @@ fn __action263< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action264< +fn __action266< >( mode: Mode, (_, e, _): (TextSize, ast::TypeParam, TextSize), @@ -35004,7 +35192,7 @@ fn __action264< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action265< +fn __action267< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -35020,43 +35208,30 @@ fn __action265< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action266< +fn __action268< >( mode: Mode, - (_, __0, _): (TextSize, (token::Tok, ArgumentList, token::Tok), TextSize), -) -> core::option::Option<(token::Tok, ArgumentList, token::Tok)> + (_, __0, _): (TextSize, ast::Arguments, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action267< +fn __action269< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option<(token::Tok, ArgumentList, token::Tok)> +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action268< ->( - mode: Mode, - (_, __0, _): (TextSize, token::Tok, TextSize), - (_, __1, _): (TextSize, ArgumentList, TextSize), - (_, __2, _): (TextSize, token::Tok, TextSize), -) -> (token::Tok, ArgumentList, token::Tok) -{ - (__0, __1, __2) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action269< +fn __action270< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -35067,7 +35242,7 @@ fn __action269< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action270< +fn __action271< >( mode: Mode, __lookbehind: &TextSize, @@ -35079,7 +35254,7 @@ fn __action270< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action271< +fn __action272< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -35091,7 +35266,7 @@ fn __action271< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action272< +fn __action273< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -35102,7 +35277,7 @@ fn __action272< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action273< +fn __action274< >( mode: Mode, __lookbehind: &TextSize, @@ -35114,7 +35289,7 @@ fn __action273< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action274< +fn __action275< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -35126,49 +35301,49 @@ fn __action274< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action275< +fn __action276< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arguments, TextSize), -) -> core::option::Option + (_, __0, _): (TextSize, ast::Parameters, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action276< +fn __action277< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action277< +fn __action278< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arguments, TextSize), -) -> ast::Arguments + (_, __0, _): (TextSize, ast::Parameters, TextSize), +) -> ast::Parameters { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action278< +fn __action279< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, param1, _): (TextSize, (Vec, Vec), TextSize), - (_, args2, _): (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + (_, param1, _): (TextSize, (Vec, Vec), TextSize), + (_, args2, _): (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { { validate_pos_params(¶m1)?; @@ -35177,7 +35352,7 @@ fn __action278< // Now gather rest of parameters: let (vararg, kwonlyargs, kwarg) = args2.unwrap_or((None, vec![], None)); - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -35190,15 +35365,15 @@ fn __action278< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action279< +fn __action280< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, param1, _): (TextSize, (Vec, Vec), TextSize), - (_, kw, _): (TextSize, Option>, TextSize), + (_, param1, _): (TextSize, (Vec, Vec), TextSize), + (_, kw, _): (TextSize, Option>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { { validate_pos_params(¶m1)?; @@ -35209,7 +35384,7 @@ fn __action279< let kwonlyargs = vec![]; let kwarg = kw; - Ok(ast::Arguments { + Ok(ast::Parameters { posonlyargs, args, kwonlyargs, @@ -35222,18 +35397,18 @@ fn __action279< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action280< +fn __action281< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, params, _): (TextSize, (Option>, Vec, Option>), TextSize), + (_, params, _): (TextSize, (Option>, Vec, Option>), TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { { let (vararg, kwonlyargs, kwarg) = params; - ast::Arguments { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs, @@ -35246,17 +35421,17 @@ fn __action280< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action281< +fn __action282< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, kwarg, _): (TextSize, Option>, TextSize), + (_, kwarg, _): (TextSize, Option>, TextSize), (_, _, _): (TextSize, core::option::Option, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { { - ast::Arguments { + ast::Parameters { posonlyargs: vec![], args: vec![], kwonlyargs: vec![], @@ -35269,7 +35444,7 @@ fn __action281< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action282< +fn __action283< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -35280,7 +35455,7 @@ fn __action282< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action283< +fn __action284< >( mode: Mode, __lookbehind: &TextSize, @@ -35292,7 +35467,7 @@ fn __action283< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action284< +fn __action285< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -35304,30 +35479,30 @@ fn __action284< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action285< +fn __action286< >( mode: Mode, - (_, __0, _): (TextSize, Vec, TextSize), -) -> core::option::Option> + (_, __0, _): (TextSize, ast::TypeParams, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action286< +fn __action287< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option> +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action287< +fn __action288< >( mode: Mode, __lookbehind: &TextSize, @@ -35339,7 +35514,7 @@ fn __action287< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action288< +fn __action289< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -35350,7 +35525,7 @@ fn __action288< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action289< +fn __action290< >( mode: Mode, (_, e, _): (TextSize, ast::Expr, TextSize), @@ -35361,7 +35536,7 @@ fn __action289< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action290< +fn __action291< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -35377,7 +35552,7 @@ fn __action290< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action291< +fn __action292< >( mode: Mode, (_, __0, _): (TextSize, ast::WithItem, TextSize), @@ -35388,7 +35563,7 @@ fn __action291< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action292< +fn __action293< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -35400,7 +35575,7 @@ fn __action292< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action293< +fn __action294< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -35413,25 +35588,18 @@ fn __action293< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action294< +fn __action295< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, context_expr, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, vars, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), + (_, __0, _): (TextSize, ast::WithItem, TextSize), ) -> ast::WithItem { - { - let optional_vars = Some(Box::new(set_context(vars, ast::ExprContext::Store))); - ast::WithItem { context_expr, optional_vars, range: (location..end_location).into() } - } + __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action295< +fn __action296< >( mode: Mode, __lookbehind: &TextSize, @@ -35443,7 +35611,7 @@ fn __action295< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action296< +fn __action297< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -35454,7 +35622,7 @@ fn __action296< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action297< +fn __action298< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -35464,19 +35632,6 @@ fn __action297< __0 } -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action298< ->( - mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, context_expr, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::WithItem -{ - ast::WithItem { context_expr, optional_vars: None, range: (location..end_location).into() } -} - #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action299< @@ -35484,15 +35639,10 @@ fn __action299< mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, context_expr, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, vars, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::WithItem { - { - let optional_vars = Some(Box::new(set_context(vars, ast::ExprContext::Store))); - ast::WithItem { context_expr, optional_vars, range: (location..end_location).into() } - } + ast::WithItem { context_expr, optional_vars: None, range: (location..end_location).into() } } #[allow(unused_variables)] @@ -35500,17 +35650,10 @@ fn __action299< fn __action300< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, context_expr, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, vars, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), + (_, __0, _): (TextSize, ast::WithItem, TextSize), ) -> ast::WithItem { - { - let optional_vars = Some(Box::new(set_context(vars, ast::ExprContext::Store))); - ast::WithItem { context_expr, optional_vars, range: (location..end_location).into() } - } + __0 } #[allow(unused_variables)] @@ -36116,6 +36259,68 @@ fn __action348< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action349< +>( + mode: Mode, + (_, __0, _): (TextSize, token::Tok, TextSize), +) -> alloc::vec::Vec +{ + alloc::vec![__0] +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action350< +>( + mode: Mode, + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), + (_, e, _): (TextSize, token::Tok, TextSize), +) -> alloc::vec::Vec +{ + { let mut v = v; v.push(e); v } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action351< +>( + mode: Mode, + (_, __0, _): (TextSize, token::Tok, TextSize), +) -> token::Tok +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action352< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitOr, right: Box::new(e2), range: (location..end_location).into() } + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action353< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action354< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36126,7 +36331,7 @@ fn __action349< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action350< +fn __action355< >( mode: Mode, __lookbehind: &TextSize, @@ -36138,7 +36343,7 @@ fn __action350< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action351< +fn __action356< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -36150,7 +36355,7 @@ fn __action351< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action352< +fn __action357< >( mode: Mode, (_, e, _): (TextSize, ast::Identifier, TextSize), @@ -36161,7 +36366,7 @@ fn __action352< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action353< +fn __action358< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -36177,7 +36382,7 @@ fn __action353< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action354< +fn __action359< >( mode: Mode, (_, __0, _): (TextSize, (token::Tok, ast::Identifier), TextSize), @@ -36188,7 +36393,7 @@ fn __action354< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action355< +fn __action360< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec<(token::Tok, ast::Identifier)>, TextSize), @@ -36200,7 +36405,7 @@ fn __action355< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action356< +fn __action361< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -36212,7 +36417,7 @@ fn __action356< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action357< +fn __action362< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -36223,7 +36428,7 @@ fn __action357< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action358< +fn __action363< >( mode: Mode, __lookbehind: &TextSize, @@ -36235,7 +36440,7 @@ fn __action358< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action359< +fn __action364< >( mode: Mode, (_, e, _): (TextSize, ast::Alias, TextSize), @@ -36246,7 +36451,7 @@ fn __action359< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action360< +fn __action365< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -36262,7 +36467,7 @@ fn __action360< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action361< +fn __action366< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -36276,7 +36481,7 @@ fn __action361< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action362< +fn __action367< >( mode: Mode, (_, __0, _): (TextSize, ast::Int, TextSize), @@ -36287,7 +36492,7 @@ fn __action362< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action363< +fn __action368< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36299,7 +36504,7 @@ fn __action363< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action364< +fn __action369< >( mode: Mode, __lookbehind: &TextSize, @@ -36311,7 +36516,7 @@ fn __action364< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action365< +fn __action370< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36322,7 +36527,7 @@ fn __action365< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action366< +fn __action371< >( mode: Mode, (_, e, _): (TextSize, ast::Alias, TextSize), @@ -36333,7 +36538,7 @@ fn __action366< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action367< +fn __action372< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -36349,7 +36554,7 @@ fn __action367< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action368< +fn __action373< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -36361,64 +36566,6 @@ fn __action368< ast::Alias { name, asname: a, range: (location..end_location).into() } } -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action369< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> core::option::Option -{ - Some(__0) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action370< ->( - mode: Mode, - __lookbehind: &TextSize, - __lookahead: &TextSize, -) -> core::option::Option -{ - None -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action371< ->( - mode: Mode, - (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr -{ - __0 -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action372< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> core::option::Option -{ - Some(__0) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action373< ->( - mode: Mode, - __lookbehind: &TextSize, - __lookahead: &TextSize, -) -> core::option::Option -{ - None -} - #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action374< @@ -36445,6 +36592,64 @@ fn __action375< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action376< +>( + mode: Mode, + (_, _, _): (TextSize, token::Tok, TextSize), + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action377< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> core::option::Option +{ + Some(__0) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action378< +>( + mode: Mode, + __lookbehind: &TextSize, + __lookahead: &TextSize, +) -> core::option::Option +{ + None +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action379< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> core::option::Option +{ + Some(__0) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action380< +>( + mode: Mode, + __lookbehind: &TextSize, + __lookahead: &TextSize, +) -> core::option::Option +{ + None +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action381< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -36468,7 +36673,7 @@ fn __action376< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action377< +fn __action382< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36479,7 +36684,7 @@ fn __action377< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action378< +fn __action383< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36490,7 +36695,7 @@ fn __action378< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action379< +fn __action384< >( mode: Mode, __lookbehind: &TextSize, @@ -36502,7 +36707,7 @@ fn __action379< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action380< +fn __action385< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36513,7 +36718,7 @@ fn __action380< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action381< +fn __action386< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -36524,7 +36729,7 @@ fn __action381< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action382< +fn __action387< >( mode: Mode, __lookbehind: &TextSize, @@ -36536,7 +36741,7 @@ fn __action382< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action383< +fn __action388< >( mode: Mode, __lookbehind: &TextSize, @@ -36548,7 +36753,7 @@ fn __action383< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action384< +fn __action389< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36559,7 +36764,7 @@ fn __action384< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action385< +fn __action390< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -36571,7 +36776,7 @@ fn __action385< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action386< +fn __action391< >( mode: Mode, __lookbehind: &TextSize, @@ -36583,7 +36788,7 @@ fn __action386< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action387< +fn __action392< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36594,7 +36799,7 @@ fn __action387< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action388< +fn __action393< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -36604,7 +36809,7 @@ fn __action388< } #[allow(unused_variables)] -fn __action389< +fn __action394< >( mode: Mode, __lookbehind: &TextSize, @@ -36615,7 +36820,7 @@ fn __action389< } #[allow(unused_variables)] -fn __action390< +fn __action395< >( mode: Mode, __lookbehind: &TextSize, @@ -36627,7 +36832,7 @@ fn __action390< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action391< +fn __action396< >( mode: Mode, (_, __0, _): (TextSize, token::Tok, TextSize), @@ -36638,7 +36843,7 @@ fn __action391< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action392< +fn __action397< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36650,7 +36855,7 @@ fn __action392< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action393< +fn __action398< >( mode: Mode, (_, __0, _): (TextSize, ast::Stmt, TextSize), @@ -36661,7 +36866,7 @@ fn __action393< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action394< +fn __action399< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36673,7 +36878,7 @@ fn __action394< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action395< +fn __action400< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36684,7 +36889,7 @@ fn __action395< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action396< +fn __action401< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36696,7 +36901,7 @@ fn __action396< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action397< +fn __action402< >( mode: Mode, (_, __0, _): (TextSize, ast::Identifier, TextSize), @@ -36707,7 +36912,7 @@ fn __action397< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action398< +fn __action403< >( mode: Mode, __lookbehind: &TextSize, @@ -36719,7 +36924,7 @@ fn __action398< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action399< +fn __action404< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -36731,7 +36936,35 @@ fn __action399< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action400< +fn __action405< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitXor, right: Box::new(e2), range: (location..end_location).into() } + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action406< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action407< >( mode: Mode, (_, __0, _): (TextSize, ast::Pattern, TextSize), @@ -36742,7 +36975,7 @@ fn __action400< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action401< +fn __action408< >( mode: Mode, __lookbehind: &TextSize, @@ -36754,7 +36987,7 @@ fn __action401< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action402< +fn __action409< >( mode: Mode, __lookbehind: &TextSize, @@ -36766,7 +36999,7 @@ fn __action402< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action403< +fn __action410< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36777,7 +37010,7 @@ fn __action403< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action404< +fn __action411< >( mode: Mode, (_, __0, _): (TextSize, (TextSize, ast::Expr, ast::Suite), TextSize), @@ -36788,7 +37021,7 @@ fn __action404< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action405< +fn __action412< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec<(TextSize, ast::Expr, ast::Suite)>, TextSize), @@ -36800,7 +37033,7 @@ fn __action405< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action406< +fn __action413< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -36824,7 +37057,7 @@ fn __action406< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action407< +fn __action414< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36835,7 +37068,7 @@ fn __action407< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action408< +fn __action415< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -36846,7 +37079,7 @@ fn __action408< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action409< +fn __action416< >( mode: Mode, (_, __0, _): (TextSize, ast::Decorator, TextSize), @@ -36857,7 +37090,7 @@ fn __action409< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action410< +fn __action417< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -36869,24 +37102,24 @@ fn __action410< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action411< +fn __action418< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, Option>, TextSize), -) -> Option> + (_, __0, _): (TextSize, Option>, TextSize), +) -> Option> { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action412< +fn __action419< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, kwarg, _): (TextSize, core::option::Option, TextSize), -) -> Option> + (_, kwarg, _): (TextSize, core::option::Option, TextSize), +) -> Option> { { kwarg.map(Box::new) @@ -36895,50 +37128,50 @@ fn __action412< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action413< +fn __action420< >( mode: Mode, - (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), -) -> core::option::Option<(Option>, Vec, Option>)> + (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), +) -> core::option::Option<(Option>, Vec, Option>)> { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action414< +fn __action421< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option<(Option>, Vec, Option>)> +) -> core::option::Option<(Option>, Vec, Option>)> { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action415< +fn __action422< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), -) -> (Option>, Vec, Option>) + (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), +) -> (Option>, Vec, Option>) { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action416< +fn __action423< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, va, _): (TextSize, core::option::Option, TextSize), - (_, kwonlyargs, _): (TextSize, alloc::vec::Vec, TextSize), - (_, kwarg, _): (TextSize, core::option::Option>>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + (_, va, _): (TextSize, core::option::Option, TextSize), + (_, kwonlyargs, _): (TextSize, alloc::vec::Vec, TextSize), + (_, kwarg, _): (TextSize, core::option::Option>>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { { if va.is_none() && kwonlyargs.is_empty() && kwarg.is_none() { @@ -36957,11 +37190,11 @@ fn __action416< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action417< +fn __action424< >( mode: Mode, - (_, args, _): (TextSize, Vec, TextSize), -) -> (Vec, Vec) + (_, args, _): (TextSize, Vec, TextSize), +) -> (Vec, Vec) { { (vec![], args) @@ -36970,14 +37203,14 @@ fn __action417< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action418< +fn __action425< >( mode: Mode, - (_, posonlyargs, _): (TextSize, Vec, TextSize), + (_, posonlyargs, _): (TextSize, Vec, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, args, _): (TextSize, alloc::vec::Vec, TextSize), -) -> (Vec, Vec) + (_, args, _): (TextSize, alloc::vec::Vec, TextSize), +) -> (Vec, Vec) { { (posonlyargs, args) @@ -36986,24 +37219,24 @@ fn __action418< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action419< +fn __action426< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, Option>, TextSize), -) -> Option> + (_, __0, _): (TextSize, Option>, TextSize), +) -> Option> { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action420< +fn __action427< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, kwarg, _): (TextSize, core::option::Option, TextSize), -) -> Option> + (_, kwarg, _): (TextSize, core::option::Option, TextSize), +) -> Option> { { kwarg.map(Box::new) @@ -37012,50 +37245,50 @@ fn __action420< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action421< +fn __action428< >( mode: Mode, - (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), -) -> core::option::Option<(Option>, Vec, Option>)> + (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), +) -> core::option::Option<(Option>, Vec, Option>)> { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action422< +fn __action429< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option<(Option>, Vec, Option>)> +) -> core::option::Option<(Option>, Vec, Option>)> { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action423< +fn __action430< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), -) -> (Option>, Vec, Option>) + (_, __0, _): (TextSize, (Option>, Vec, Option>), TextSize), +) -> (Option>, Vec, Option>) { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action424< +fn __action431< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, va, _): (TextSize, core::option::Option, TextSize), - (_, kwonlyargs, _): (TextSize, alloc::vec::Vec, TextSize), - (_, kwarg, _): (TextSize, core::option::Option>>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + (_, va, _): (TextSize, core::option::Option, TextSize), + (_, kwonlyargs, _): (TextSize, alloc::vec::Vec, TextSize), + (_, kwarg, _): (TextSize, core::option::Option>>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { { if va.is_none() && kwonlyargs.is_empty() && kwarg.is_none() { @@ -37074,11 +37307,11 @@ fn __action424< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action425< +fn __action432< >( mode: Mode, - (_, args, _): (TextSize, Vec, TextSize), -) -> (Vec, Vec) + (_, args, _): (TextSize, Vec, TextSize), +) -> (Vec, Vec) { { (vec![], args) @@ -37087,14 +37320,14 @@ fn __action425< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action426< +fn __action433< >( mode: Mode, - (_, posonlyargs, _): (TextSize, Vec, TextSize), + (_, posonlyargs, _): (TextSize, Vec, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, args, _): (TextSize, alloc::vec::Vec, TextSize), -) -> (Vec, Vec) + (_, args, _): (TextSize, alloc::vec::Vec, TextSize), +) -> (Vec, Vec) { { (posonlyargs, args) @@ -37103,35 +37336,7 @@ fn __action426< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action427< ->( - mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitXor, right: Box::new(e2), range: (location..end_location).into() } - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action428< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr -{ - __0 -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action429< +fn __action434< >( mode: Mode, (_, e, _): (TextSize, ast::Expr, TextSize), @@ -37142,7 +37347,7 @@ fn __action429< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action430< +fn __action435< >( mode: Mode, (_, mut v, _): (TextSize, Vec, TextSize), @@ -37158,7 +37363,7 @@ fn __action430< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action431< +fn __action436< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37169,7 +37374,7 @@ fn __action431< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action432< +fn __action437< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -37181,7 +37386,7 @@ fn __action432< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action433< +fn __action438< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37193,7 +37398,7 @@ fn __action433< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action434< +fn __action439< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -37212,7 +37417,7 @@ fn __action434< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action435< +fn __action440< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37223,7 +37428,7 @@ fn __action435< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action436< +fn __action441< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37234,7 +37439,7 @@ fn __action436< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action437< +fn __action442< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -37246,7 +37451,7 @@ fn __action437< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action438< +fn __action443< >( mode: Mode, (_, __0, _): (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), @@ -37257,7 +37462,7 @@ fn __action438< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action439< +fn __action444< >( mode: Mode, __lookbehind: &TextSize, @@ -37269,7 +37474,7 @@ fn __action439< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action440< +fn __action445< >( mode: Mode, __lookbehind: &TextSize, @@ -37281,7 +37486,7 @@ fn __action440< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action441< +fn __action446< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -37292,7 +37497,7 @@ fn __action441< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action442< +fn __action447< >( mode: Mode, (_, __0, _): (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), @@ -37304,7 +37509,7 @@ fn __action442< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action443< +fn __action448< >( mode: Mode, (_, __0, _): (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), @@ -37315,7 +37520,7 @@ fn __action443< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action444< +fn __action449< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -37327,61 +37532,34 @@ fn __action444< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action445< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> alloc::vec::Vec -{ - alloc::vec![__0] -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action446< ->( - mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), -) -> alloc::vec::Vec -{ - { let mut v = v; v.push(e); v } -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action447< +fn __action450< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), -) -> ast::Expr +) -> alloc::vec::Vec { - __0 + alloc::vec![__0] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action448< +fn __action451< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), (_, e, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr +) -> alloc::vec::Vec { - ast::Expr::UnaryOp( - ast::ExprUnaryOp { operand: Box::new(e), op: ast::UnaryOp::Not, range: (location..end_location).into() } - ) + { let mut v = v; v.push(e); v } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action449< +fn __action452< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), ) -> ast::Expr { __0 @@ -37389,24 +37567,23 @@ fn __action449< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action450< +fn __action453< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitAnd, right: Box::new(e2), range: (location..end_location).into() } + ast::Expr::UnaryOp( + ast::ExprUnaryOp { operand: Box::new(e), op: ast::UnaryOp::Not, range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action451< +fn __action454< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37417,24 +37594,24 @@ fn __action451< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action452< +fn __action455< >( mode: Mode, - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> Vec + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> Vec { vec![e] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action453< +fn __action456< >( mode: Mode, - (_, mut v, _): (TextSize, Vec, TextSize), + (_, mut v, _): (TextSize, Vec, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> Vec + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> Vec { { v.push(e); @@ -37444,83 +37621,83 @@ fn __action453< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action454< +fn __action457< >( mode: Mode, - (_, __0, _): (TextSize, Option>, TextSize), -) -> core::option::Option>> + (_, __0, _): (TextSize, Option>, TextSize), +) -> core::option::Option>> { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action455< +fn __action458< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option>> +) -> core::option::Option>> { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action456< +fn __action459< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> alloc::vec::Vec +) -> alloc::vec::Vec { alloc::vec![] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action457< +fn __action460< >( mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), -) -> alloc::vec::Vec + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), +) -> alloc::vec::Vec { v } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action458< +fn __action461< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> ast::ArgWithDefault + (_, __0, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> ast::ParameterWithDefault { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action459< +fn __action462< >( mode: Mode, - (_, i, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> ast::ArgWithDefault + (_, i, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> ast::ParameterWithDefault { i } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action460< +fn __action463< >( mode: Mode, - (_, mut i, _): (TextSize, ast::ArgWithDefault, TextSize), + (_, mut i, _): (TextSize, ast::ParameterWithDefault, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, e, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { { i.default = Some(Box::new(e)); @@ -37531,47 +37708,47 @@ fn __action460< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action461< +fn __action464< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arg, TextSize), -) -> core::option::Option + (_, __0, _): (TextSize, ast::Parameter, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action462< +fn __action465< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action463< +fn __action466< >( mode: Mode, - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> Vec + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> Vec { vec![e] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action464< +fn __action467< >( mode: Mode, - (_, mut v, _): (TextSize, Vec, TextSize), + (_, mut v, _): (TextSize, Vec, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> Vec + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> Vec { { v.push(e); @@ -37581,83 +37758,83 @@ fn __action464< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action465< +fn __action468< >( mode: Mode, - (_, __0, _): (TextSize, Option>, TextSize), -) -> core::option::Option>> + (_, __0, _): (TextSize, Option>, TextSize), +) -> core::option::Option>> { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action466< +fn __action469< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option>> +) -> core::option::Option>> { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action467< +fn __action470< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> alloc::vec::Vec +) -> alloc::vec::Vec { alloc::vec![] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action468< +fn __action471< >( mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), -) -> alloc::vec::Vec + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), +) -> alloc::vec::Vec { v } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action469< +fn __action472< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), - (_, __0, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> ast::ArgWithDefault + (_, __0, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> ast::ParameterWithDefault { __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action470< +fn __action473< >( mode: Mode, - (_, i, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> ast::ArgWithDefault + (_, i, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> ast::ParameterWithDefault { i } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action471< +fn __action474< >( mode: Mode, - (_, mut i, _): (TextSize, ast::ArgWithDefault, TextSize), + (_, mut i, _): (TextSize, ast::ParameterWithDefault, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), (_, e, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { { i.default = Some(Box::new(e)); @@ -37668,53 +37845,53 @@ fn __action471< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action472< +fn __action475< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arg, TextSize), -) -> core::option::Option + (_, __0, _): (TextSize, ast::Parameter, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action473< +fn __action476< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action474< +fn __action477< >( mode: Mode, - (_, __0, _): (TextSize, ast::Arg, TextSize), -) -> core::option::Option + (_, __0, _): (TextSize, ast::Parameter, TextSize), +) -> core::option::Option { Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action475< +fn __action478< >( mode: Mode, __lookbehind: &TextSize, __lookahead: &TextSize, -) -> core::option::Option +) -> core::option::Option { None } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action476< +fn __action479< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -37733,7 +37910,7 @@ fn __action476< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action477< +fn __action480< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37744,26 +37921,24 @@ fn __action477< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action478< +fn __action481< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, mut values, _): (TextSize, alloc::vec::Vec, TextSize), - (_, last, _): (TextSize, ast::Expr, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - { - values.push(last); - ast::Expr::BoolOp( - ast::ExprBoolOp { op: ast::BoolOp::And, values, range: (location..end_location).into() } - ) - } + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitAnd, right: Box::new(e2), range: (location..end_location).into() } + ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action479< +fn __action482< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37774,81 +37949,111 @@ fn __action479< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action480< +fn __action483< >( mode: Mode, - (_, __0, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + (_, location, _): (TextSize, TextSize, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, op, _): (TextSize, ast::Operator, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr { - alloc::vec![__0] + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(e1), op, right: Box::new(e2), range: (location..end_location).into() } + ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action481< +fn __action484< >( mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr { - { let mut v = v; v.push(e); v } + __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action482< +fn __action485< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, mut values, _): (TextSize, alloc::vec::Vec, TextSize), + (_, last, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + { + values.push(last); + ast::Expr::BoolOp( + ast::ExprBoolOp { op: ast::BoolOp::And, values, range: (location..end_location).into() } + ) + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action486< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action487< >( mode: Mode, - (_, __0, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + (_, __0, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { alloc::vec![__0] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action483< +fn __action488< >( mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), - (_, e, _): (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { { let mut v = v; v.push(e); v } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action484< +fn __action489< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), - (_, op, _): (TextSize, ast::Operator, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr + (_, __0, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op, right: Box::new(e2), range: (location..end_location).into() } - ) + alloc::vec![__0] } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action485< +fn __action490< >( mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), + (_, e, _): (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { - __0 + { let mut v = v; v.push(e); v } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action486< +fn __action491< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -37867,7 +38072,7 @@ fn __action486< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action487< +fn __action492< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37878,7 +38083,7 @@ fn __action487< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action488< +fn __action493< >( mode: Mode, (_, __0, _): (TextSize, (ast::CmpOp, ast::Expr), TextSize), @@ -37889,7 +38094,7 @@ fn __action488< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action489< +fn __action494< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec<(ast::CmpOp, ast::Expr)>, TextSize), @@ -37901,7 +38106,7 @@ fn __action489< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action490< +fn __action495< >( mode: Mode, (_, __0, _): (TextSize, ast::CmpOp, TextSize), @@ -37913,7 +38118,34 @@ fn __action490< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action491< +fn __action496< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + ast::Expr::UnaryOp( + ast::ExprUnaryOp { operand: Box::new(e), op: ast::UnaryOp::Not, range: (location..end_location).into() } + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action497< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action498< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -37930,7 +38162,7 @@ fn __action491< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action492< +fn __action499< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37941,23 +38173,24 @@ fn __action492< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action493< +fn __action500< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), + (_, a, _): (TextSize, ast::Expr, TextSize), + (_, op, _): (TextSize, ast::Operator, TextSize), + (_, b, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - ast::Expr::UnaryOp( - ast::ExprUnaryOp { operand: Box::new(e), op: ast::UnaryOp::Not, range: (location..end_location).into() } + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action494< +fn __action501< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37968,7 +38201,7 @@ fn __action494< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action495< +fn __action502< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -37987,7 +38220,7 @@ fn __action495< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action496< +fn __action503< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -37998,24 +38231,24 @@ fn __action496< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action497< +fn __action504< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, a, _): (TextSize, ast::Expr, TextSize), - (_, op, _): (TextSize, ast::Operator, TextSize), - (_, b, _): (TextSize, ast::Expr, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } + ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitOr, right: Box::new(e2), range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action498< +fn __action505< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38026,7 +38259,7 @@ fn __action498< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action499< +fn __action506< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38042,7 +38275,7 @@ fn __action499< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action500< +fn __action507< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38053,24 +38286,24 @@ fn __action500< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action501< +fn __action508< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, b, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitOr, right: Box::new(e2), range: (location..end_location).into() } + ast::ExprBinOp { left: Box::new(e), op: ast::Operator::Pow, right: Box::new(b), range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action502< +fn __action509< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38081,7 +38314,7 @@ fn __action502< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action503< +fn __action510< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38098,7 +38331,7 @@ fn __action503< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action504< +fn __action511< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38109,24 +38342,24 @@ fn __action504< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action505< +fn __action512< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), (_, _, _): (TextSize, token::Tok, TextSize), - (_, b, _): (TextSize, ast::Expr, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e), op: ast::Operator::Pow, right: Box::new(b), range: (location..end_location).into() } + ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitAnd, right: Box::new(e2), range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action506< +fn __action513< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38137,7 +38370,7 @@ fn __action506< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action507< +fn __action514< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38155,7 +38388,7 @@ fn __action507< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action508< +fn __action515< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38166,129 +38399,127 @@ fn __action508< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action509< +fn __action516< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), + (_, __0, _): (TextSize, ast::Expr, TextSize), ) -> ast::Expr { - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op: ast::Operator::BitAnd, right: Box::new(e2), range: (location..end_location).into() } - ) + __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action510< +fn __action517< >( mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), + (_, location, _): (TextSize, TextSize, TextSize), + (_, f, _): (TextSize, ast::Expr, TextSize), + (_, arguments, _): (TextSize, ast::Arguments, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - __0 + { + ast::Expr::Call( + ast::ExprCall { func: Box::new(f), arguments, range: (location..end_location).into() } + ) + } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action511< +fn __action518< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, e1, _): (TextSize, ast::Expr, TextSize), - (_, op, _): (TextSize, ast::Operator, TextSize), - (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, s, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(e1), op, right: Box::new(e2), range: (location..end_location).into() } + ast::Expr::Subscript( + ast::ExprSubscript { value: Box::new(e), slice: Box::new(s), ctx: ast::ExprContext::Load, range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action512< +fn __action519< >( mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), + (_, location, _): (TextSize, TextSize, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), + (_, attr, _): (TextSize, ast::Identifier, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - __0 + ast::Expr::Attribute( + ast::ExprAttribute { value: Box::new(e), attr, ctx: ast::ExprContext::Load, range: (location..end_location).into() } + ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action513< +fn __action520< >( mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), + (_, location, _): (TextSize, TextSize, TextSize), + (_, e1, _): (TextSize, ast::Expr, TextSize), + (_, op, _): (TextSize, ast::Operator, TextSize), + (_, e2, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - __0 + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(e1), op, right: Box::new(e2), range: (location..end_location).into() } + ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action514< +fn __action521< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, f, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, a, _): (TextSize, ArgumentList, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), + (_, __0, _): (TextSize, ast::Expr, TextSize), ) -> ast::Expr { - { - ast::Expr::Call( - ast::ExprCall { func: Box::new(f), args: a.args, keywords: a.keywords, range: (location..end_location).into() } - ) - } + __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action515< +fn __action522< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, s, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), + (_, a, _): (TextSize, ast::Expr, TextSize), + (_, op, _): (TextSize, ast::Operator, TextSize), + (_, b, _): (TextSize, ast::Expr, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { - ast::Expr::Subscript( - ast::ExprSubscript { value: Box::new(e), slice: Box::new(s), ctx: ast::ExprContext::Load, range: (location..end_location).into() } + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action516< +fn __action523< >( mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, attr, _): (TextSize, ast::Identifier, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), + (_, __0, _): (TextSize, ast::Expr, TextSize), ) -> ast::Expr { - ast::Expr::Attribute( - ast::ExprAttribute { value: Box::new(e), attr, ctx: ast::ExprContext::Load, range: (location..end_location).into() } - ) + __0 } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action517< +fn __action524< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38300,7 +38531,7 @@ fn __action517< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action518< +fn __action525< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38315,7 +38546,7 @@ fn __action518< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action519< +fn __action526< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38330,7 +38561,7 @@ fn __action519< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action520< +fn __action527< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38350,7 +38581,7 @@ fn __action520< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action521< +fn __action528< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38370,7 +38601,7 @@ fn __action521< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action522< +fn __action529< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38394,7 +38625,7 @@ fn __action522< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action523< +fn __action530< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38427,7 +38658,7 @@ fn __action523< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action524< +fn __action531< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38443,7 +38674,7 @@ fn __action524< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action525< +fn __action532< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -38456,7 +38687,7 @@ fn __action525< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action526< +fn __action533< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38476,7 +38707,7 @@ fn __action526< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action527< +fn __action534< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -38497,7 +38728,7 @@ fn __action527< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action528< +fn __action535< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38521,7 +38752,7 @@ fn __action528< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action529< +fn __action536< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38546,7 +38777,7 @@ fn __action529< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action530< +fn __action537< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38563,7 +38794,7 @@ fn __action530< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action531< +fn __action538< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38583,7 +38814,7 @@ fn __action531< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action532< +fn __action539< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38596,7 +38827,7 @@ fn __action532< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action533< +fn __action540< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38609,7 +38840,7 @@ fn __action533< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action534< +fn __action541< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38622,7 +38853,7 @@ fn __action534< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action535< +fn __action542< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38635,63 +38866,7 @@ fn __action535< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action536< ->( - mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, a, _): (TextSize, ast::Expr, TextSize), - (_, op, _): (TextSize, ast::Operator, TextSize), - (_, b, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action537< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr -{ - __0 -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action538< ->( - mode: Mode, - (_, location, _): (TextSize, TextSize, TextSize), - (_, a, _): (TextSize, ast::Expr, TextSize), - (_, op, _): (TextSize, ast::Operator, TextSize), - (_, b, _): (TextSize, ast::Expr, TextSize), - (_, end_location, _): (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - ast::Expr::BinOp( - ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action539< ->( - mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> ast::Expr -{ - __0 -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action540< +fn __action543< >( mode: Mode, (_, __0, _): (TextSize, Vec<(Option>, ast::Expr)>, TextSize), @@ -38702,7 +38877,7 @@ fn __action540< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action541< +fn __action544< >( mode: Mode, __lookbehind: &TextSize, @@ -38714,7 +38889,7 @@ fn __action541< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action542< +fn __action545< >( mode: Mode, __lookbehind: &TextSize, @@ -38726,7 +38901,7 @@ fn __action542< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action543< +fn __action546< >( mode: Mode, (_, v, _): (TextSize, alloc::vec::Vec, TextSize), @@ -38737,7 +38912,7 @@ fn __action543< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action544< +fn __action547< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -38747,41 +38922,6 @@ fn __action544< __0 } -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action545< ->( - mode: Mode, - (_, __0, _): (TextSize, Vec, TextSize), -) -> core::option::Option> -{ - Some(__0) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action546< ->( - mode: Mode, - __lookbehind: &TextSize, - __lookahead: &TextSize, -) -> core::option::Option> -{ - None -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action547< ->( - mode: Mode, - (_, __0, _): (TextSize, Vec, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), -) -> Vec -{ - __0 -} - #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action548< @@ -38810,10 +38950,11 @@ fn __action549< fn __action550< >( mode: Mode, - (_, __0, _): (TextSize, ast::Expr, TextSize), -) -> alloc::vec::Vec + (_, __0, _): (TextSize, Vec, TextSize), + (_, _, _): (TextSize, token::Tok, TextSize), +) -> Vec { - alloc::vec![__0] + __0 } #[allow(unused_variables)] @@ -38821,16 +38962,55 @@ fn __action550< fn __action551< >( mode: Mode, - (_, v, _): (TextSize, alloc::vec::Vec, TextSize), - (_, e, _): (TextSize, ast::Expr, TextSize), -) -> alloc::vec::Vec + (_, __0, _): (TextSize, Vec, TextSize), +) -> core::option::Option> { - { let mut v = v; v.push(e); v } + Some(__0) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action552< +>( + mode: Mode, + __lookbehind: &TextSize, + __lookahead: &TextSize, +) -> core::option::Option> +{ + None +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action553< +>( + mode: Mode, + (_, location, _): (TextSize, TextSize, TextSize), + (_, a, _): (TextSize, ast::Expr, TextSize), + (_, op, _): (TextSize, ast::Operator, TextSize), + (_, b, _): (TextSize, ast::Expr, TextSize), + (_, end_location, _): (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + ast::Expr::BinOp( + ast::ExprBinOp { left: Box::new(a), op, right: Box::new(b), range: (location..end_location).into() } + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action554< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> ast::Expr +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action555< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38846,7 +39026,7 @@ fn __action552< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action553< +fn __action556< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38857,7 +39037,30 @@ fn __action553< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action554< +fn __action557< +>( + mode: Mode, + (_, __0, _): (TextSize, ast::Expr, TextSize), +) -> alloc::vec::Vec +{ + alloc::vec![__0] +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action558< +>( + mode: Mode, + (_, v, _): (TextSize, alloc::vec::Vec, TextSize), + (_, e, _): (TextSize, ast::Expr, TextSize), +) -> alloc::vec::Vec +{ + { let mut v = v; v.push(e); v } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action559< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38874,7 +39077,7 @@ fn __action554< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action555< +fn __action560< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38885,7 +39088,7 @@ fn __action555< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action556< +fn __action561< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38903,7 +39106,7 @@ fn __action556< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action557< +fn __action562< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38914,7 +39117,7 @@ fn __action557< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action558< +fn __action563< >( mode: Mode, (_, __0, _): (TextSize, ast::Expr, TextSize), @@ -38925,27 +39128,25 @@ fn __action558< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action559< +fn __action564< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), (_, f, _): (TextSize, ast::Expr, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), - (_, a, _): (TextSize, ArgumentList, TextSize), - (_, _, _): (TextSize, token::Tok, TextSize), + (_, arguments, _): (TextSize, ast::Arguments, TextSize), (_, end_location, _): (TextSize, TextSize, TextSize), ) -> ast::Expr { { ast::Expr::Call( - ast::ExprCall { func: Box::new(f), args: a.args, keywords: a.keywords, range: (location..end_location).into() } + ast::ExprCall { func: Box::new(f), arguments, range: (location..end_location).into() } ) } } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action560< +fn __action565< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38963,7 +39164,7 @@ fn __action560< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action561< +fn __action566< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38980,7 +39181,7 @@ fn __action561< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action562< +fn __action567< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -38992,7 +39193,7 @@ fn __action562< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action563< +fn __action568< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39007,7 +39208,7 @@ fn __action563< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action564< +fn __action569< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39022,7 +39223,7 @@ fn __action564< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action565< +fn __action570< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39042,7 +39243,7 @@ fn __action565< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action566< +fn __action571< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39062,7 +39263,7 @@ fn __action566< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action567< +fn __action572< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39095,7 +39296,7 @@ fn __action567< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action568< +fn __action573< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39111,7 +39312,7 @@ fn __action568< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action569< +fn __action574< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -39124,7 +39325,7 @@ fn __action569< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action570< +fn __action575< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39144,7 +39345,7 @@ fn __action570< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action571< +fn __action576< >( mode: Mode, (_, _, _): (TextSize, token::Tok, TextSize), @@ -39165,7 +39366,7 @@ fn __action571< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action572< +fn __action577< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39189,7 +39390,7 @@ fn __action572< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action573< +fn __action578< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39214,7 +39415,7 @@ fn __action573< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action574< +fn __action579< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39231,7 +39432,7 @@ fn __action574< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action575< +fn __action580< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39251,7 +39452,7 @@ fn __action575< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action576< +fn __action581< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39264,7 +39465,7 @@ fn __action576< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action577< +fn __action582< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39277,7 +39478,7 @@ fn __action577< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action578< +fn __action583< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39290,7 +39491,7 @@ fn __action578< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action579< +fn __action584< >( mode: Mode, (_, location, _): (TextSize, TextSize, TextSize), @@ -39303,7 +39504,7 @@ fn __action579< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action580< +fn __action585< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39316,12 +39517,12 @@ fn __action580< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action522( + __action529( mode, __0, __1, @@ -39334,7 +39535,7 @@ fn __action580< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action581< +fn __action586< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39346,13 +39547,13 @@ fn __action581< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action522( + __action529( mode, __0, __1, @@ -39365,7 +39566,7 @@ fn __action581< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action582< +fn __action587< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39380,12 +39581,12 @@ fn __action582< { let __start0 = __5.0; let __end0 = __5.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __5, ); let __temp0 = (__start0, __temp0, __end0); - __action523( + __action530( mode, __0, __1, @@ -39400,7 +39601,7 @@ fn __action582< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action583< +fn __action588< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39414,13 +39615,13 @@ fn __action583< { let __start0 = __4.2; let __end0 = __5.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action523( + __action530( mode, __0, __1, @@ -39435,7 +39636,7 @@ fn __action583< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action584< +fn __action589< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39450,12 +39651,12 @@ fn __action584< { let __start0 = __5.0; let __end0 = __5.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __5, ); let __temp0 = (__start0, __temp0, __end0); - __action567( + __action572( mode, __0, __1, @@ -39470,7 +39671,7 @@ fn __action584< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action585< +fn __action590< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39484,13 +39685,13 @@ fn __action585< { let __start0 = __4.2; let __end0 = __5.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action567( + __action572( mode, __0, __1, @@ -39505,7 +39706,7 @@ fn __action585< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action586< +fn __action591< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39521,12 +39722,12 @@ fn __action586< { let __start0 = __6.0; let __end0 = __6.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action137( + __action139( mode, __0, __1, @@ -39542,7 +39743,7 @@ fn __action586< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action587< +fn __action592< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39557,13 +39758,13 @@ fn __action587< { let __start0 = __5.2; let __end0 = __6.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action137( + __action139( mode, __0, __1, @@ -39579,7 +39780,7 @@ fn __action587< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action588< +fn __action593< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39593,12 +39794,12 @@ fn __action588< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action138( + __action140( mode, __0, __1, @@ -39612,7 +39813,7 @@ fn __action588< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action589< +fn __action594< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39625,13 +39826,13 @@ fn __action589< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action138( + __action140( mode, __0, __1, @@ -39645,7 +39846,7 @@ fn __action589< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action590< +fn __action595< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39659,12 +39860,12 @@ fn __action590< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action139( + __action141( mode, __0, __1, @@ -39678,7 +39879,7 @@ fn __action590< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action591< +fn __action596< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39691,13 +39892,13 @@ fn __action591< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action139( + __action141( mode, __0, __1, @@ -39711,7 +39912,7 @@ fn __action591< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action592< +fn __action597< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39727,12 +39928,12 @@ fn __action592< { let __start0 = __6.0; let __end0 = __6.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action141( + __action143( mode, __0, __1, @@ -39748,7 +39949,7 @@ fn __action592< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action593< +fn __action598< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39763,13 +39964,13 @@ fn __action593< { let __start0 = __5.2; let __end0 = __6.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action141( + __action143( mode, __0, __1, @@ -39785,7 +39986,7 @@ fn __action593< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action594< +fn __action599< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39799,12 +40000,12 @@ fn __action594< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action142( + __action144( mode, __0, __1, @@ -39818,7 +40019,7 @@ fn __action594< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action595< +fn __action600< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39831,13 +40032,13 @@ fn __action595< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action142( + __action144( mode, __0, __1, @@ -39851,7 +40052,7 @@ fn __action595< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action596< +fn __action601< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39865,12 +40066,12 @@ fn __action596< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action143( + __action145( mode, __0, __1, @@ -39884,7 +40085,7 @@ fn __action596< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action597< +fn __action602< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -39897,13 +40098,13 @@ fn __action597< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action143( + __action145( mode, __0, __1, @@ -39917,7 +40118,7 @@ fn __action597< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action598< +fn __action603< >( mode: Mode, __0: (TextSize, Vec<(Option>, ast::Expr)>, TextSize), @@ -39926,12 +40127,12 @@ fn __action598< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action211( + __action215( mode, __0, __temp0, @@ -39940,7 +40141,7 @@ fn __action598< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action599< +fn __action604< >( mode: Mode, __0: (TextSize, Vec<(Option>, ast::Expr)>, TextSize), @@ -39948,13 +40149,13 @@ fn __action599< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action211( + __action215( mode, __0, __temp0, @@ -39963,7 +40164,7 @@ fn __action599< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action600< +fn __action605< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -39972,12 +40173,12 @@ fn __action600< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action219( + __action223( mode, __0, __temp0, @@ -39986,7 +40187,7 @@ fn __action600< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action601< +fn __action606< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -39994,13 +40195,13 @@ fn __action601< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action219( + __action223( mode, __0, __temp0, @@ -40009,7 +40210,7 @@ fn __action601< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action602< +fn __action607< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40020,12 +40221,12 @@ fn __action602< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action247( + __action251( mode, __0, __1, @@ -40036,7 +40237,7 @@ fn __action602< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action603< +fn __action608< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40046,13 +40247,13 @@ fn __action603< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action247( + __action251( mode, __0, __1, @@ -40063,7 +40264,7 @@ fn __action603< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action604< +fn __action609< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40074,12 +40275,12 @@ fn __action604< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action244( + __action248( mode, __0, __1, @@ -40090,7 +40291,7 @@ fn __action604< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action605< +fn __action610< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40100,13 +40301,13 @@ fn __action605< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action244( + __action248( mode, __0, __1, @@ -40117,7 +40318,7 @@ fn __action605< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action606< +fn __action611< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40130,12 +40331,12 @@ fn __action606< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action66( + __action67( mode, __0, __1, @@ -40148,7 +40349,7 @@ fn __action606< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action607< +fn __action612< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40160,13 +40361,13 @@ fn __action607< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action66( + __action67( mode, __0, __1, @@ -40179,7 +40380,7 @@ fn __action607< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action608< +fn __action613< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -40188,12 +40389,12 @@ fn __action608< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action210( + __action214( mode, __0, __temp0, @@ -40202,7 +40403,7 @@ fn __action608< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action609< +fn __action614< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -40210,13 +40411,13 @@ fn __action609< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action210( + __action214( mode, __0, __temp0, @@ -40225,7 +40426,7 @@ fn __action609< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action610< +fn __action615< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40238,12 +40439,12 @@ fn __action610< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action133( + __action135( mode, __0, __1, @@ -40256,7 +40457,7 @@ fn __action610< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action611< +fn __action616< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40268,13 +40469,13 @@ fn __action611< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action133( + __action135( mode, __0, __1, @@ -40287,7 +40488,7 @@ fn __action611< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action612< +fn __action617< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40301,12 +40502,12 @@ fn __action612< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action134( + __action136( mode, __0, __1, @@ -40320,7 +40521,7 @@ fn __action612< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action613< +fn __action618< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40333,13 +40534,13 @@ fn __action613< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action134( + __action136( mode, __0, __1, @@ -40353,7 +40554,7 @@ fn __action613< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action614< +fn __action619< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40369,12 +40570,12 @@ fn __action614< { let __start0 = __6.0; let __end0 = __6.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action135( + __action137( mode, __0, __1, @@ -40390,7 +40591,7 @@ fn __action614< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action615< +fn __action620< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40405,13 +40606,13 @@ fn __action615< { let __start0 = __5.2; let __end0 = __6.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action135( + __action137( mode, __0, __1, @@ -40427,7 +40628,7 @@ fn __action615< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action616< +fn __action621< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40443,12 +40644,12 @@ fn __action616< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action85( + __action87( mode, __0, __1, @@ -40464,7 +40665,7 @@ fn __action616< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action617< +fn __action622< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40479,13 +40680,13 @@ fn __action617< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action85( + __action87( mode, __0, __1, @@ -40501,24 +40702,24 @@ fn __action617< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action618< +fn __action623< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action278( + __action279( mode, __0, __1, @@ -40530,24 +40731,24 @@ fn __action618< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action619< +fn __action624< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action278( + __action279( mode, __0, __1, @@ -40559,24 +40760,24 @@ fn __action619< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action620< +fn __action625< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, Option>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action279( + __action280( mode, __0, __1, @@ -40588,24 +40789,24 @@ fn __action620< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action621< +fn __action626< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, Option>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action279( + __action280( mode, __0, __1, @@ -40617,23 +40818,23 @@ fn __action621< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action622< +fn __action627< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Option>, Vec, Option>), TextSize), + __1: (TextSize, (Option>, Vec, Option>), TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action280( + __action281( mode, __0, __1, @@ -40644,23 +40845,23 @@ fn __action622< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action623< +fn __action628< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Option>, Vec, Option>), TextSize), + __1: (TextSize, (Option>, Vec, Option>), TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action280( + __action281( mode, __0, __1, @@ -40671,23 +40872,23 @@ fn __action623< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action624< +fn __action629< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, Option>, TextSize), + __1: (TextSize, Option>, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action281( + __action282( mode, __0, __1, @@ -40698,23 +40899,23 @@ fn __action624< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action625< +fn __action630< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, Option>, TextSize), + __1: (TextSize, Option>, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action281( + __action282( mode, __0, __1, @@ -40725,24 +40926,24 @@ fn __action625< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action626< +fn __action631< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action260( + __action262( mode, __0, __1, @@ -40754,24 +40955,24 @@ fn __action626< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action627< +fn __action632< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action260( + __action262( mode, __0, __1, @@ -40783,24 +40984,24 @@ fn __action627< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action628< +fn __action633< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, Option>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action261( + __action263( mode, __0, __1, @@ -40812,24 +41013,24 @@ fn __action628< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action629< +fn __action634< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), - __2: (TextSize, Option>, TextSize), + __1: (TextSize, (Vec, Vec), TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action261( + __action263( mode, __0, __1, @@ -40841,23 +41042,23 @@ fn __action629< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action630< +fn __action635< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Option>, Vec, Option>), TextSize), + __1: (TextSize, (Option>, Vec, Option>), TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action262( + __action264( mode, __0, __1, @@ -40868,23 +41069,23 @@ fn __action630< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action631< +fn __action636< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Option>, Vec, Option>), TextSize), + __1: (TextSize, (Option>, Vec, Option>), TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action262( + __action264( mode, __0, __1, @@ -40895,23 +41096,23 @@ fn __action631< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action632< +fn __action637< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, Option>, TextSize), + __1: (TextSize, Option>, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action263( + __action265( mode, __0, __1, @@ -40922,23 +41123,23 @@ fn __action632< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action633< +fn __action638< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, Option>, TextSize), + __1: (TextSize, Option>, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action263( + __action265( mode, __0, __1, @@ -40949,7 +41150,7 @@ fn __action633< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action634< +fn __action639< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40960,12 +41161,12 @@ fn __action634< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action89( + __action91( mode, __0, __1, @@ -40976,7 +41177,7 @@ fn __action634< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action635< +fn __action640< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -40986,13 +41187,13 @@ fn __action635< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action89( + __action91( mode, __0, __1, @@ -41003,7 +41204,7 @@ fn __action635< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action636< +fn __action641< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41017,12 +41218,12 @@ fn __action636< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action106( + __action108( mode, __0, __1, @@ -41036,7 +41237,7 @@ fn __action636< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action637< +fn __action642< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41049,13 +41250,13 @@ fn __action637< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action106( + __action108( mode, __0, __1, @@ -41069,7 +41270,7 @@ fn __action637< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action638< +fn __action643< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -41078,12 +41279,12 @@ fn __action638< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action215( + __action219( mode, __0, __temp0, @@ -41092,7 +41293,7 @@ fn __action638< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action639< +fn __action644< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -41100,13 +41301,13 @@ fn __action639< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action215( + __action219( mode, __0, __temp0, @@ -41115,7 +41316,7 @@ fn __action639< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action640< +fn __action645< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41126,12 +41327,12 @@ fn __action640< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action206( + __action210( mode, __0, __1, @@ -41142,7 +41343,7 @@ fn __action640< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action641< +fn __action646< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41152,13 +41353,13 @@ fn __action641< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action206( + __action210( mode, __0, __1, @@ -41169,7 +41370,7 @@ fn __action641< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action642< +fn __action647< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41178,16 +41379,16 @@ fn __action642< __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action171( + __action174( mode, __0, __1, @@ -41200,7 +41401,7 @@ fn __action642< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action643< +fn __action648< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41208,17 +41409,17 @@ fn __action643< __2: (TextSize, Vec, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action171( + __action174( mode, __0, __1, @@ -41231,7 +41432,7 @@ fn __action643< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action644< +fn __action649< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -41242,12 +41443,12 @@ fn __action644< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action156( + __action158( mode, __0, __1, @@ -41258,7 +41459,7 @@ fn __action644< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action645< +fn __action650< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -41268,13 +41469,13 @@ fn __action645< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action156( + __action158( mode, __0, __1, @@ -41285,7 +41486,7 @@ fn __action645< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action646< +fn __action651< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -41298,12 +41499,12 @@ fn __action646< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action357( + let __temp0 = __action362( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action157( + __action159( mode, __0, __1, @@ -41316,7 +41517,7 @@ fn __action646< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action647< +fn __action652< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -41328,13 +41529,13 @@ fn __action647< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action358( + let __temp0 = __action363( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action157( + __action159( mode, __0, __1, @@ -41347,7 +41548,7 @@ fn __action647< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action648< +fn __action653< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -41359,7 +41560,7 @@ fn __action648< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action381( + let __temp0 = __action386( mode, __3, ); @@ -41376,7 +41577,7 @@ fn __action648< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action649< +fn __action654< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -41387,7 +41588,7 @@ fn __action649< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action382( + let __temp0 = __action387( mode, &__start0, &__end0, @@ -41405,7 +41606,7 @@ fn __action649< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action650< +fn __action655< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -41416,7 +41617,7 @@ fn __action650< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action381( + let __temp0 = __action386( mode, __2, ); @@ -41432,7 +41633,7 @@ fn __action650< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action651< +fn __action656< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -41442,7 +41643,7 @@ fn __action651< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action382( + let __temp0 = __action387( mode, &__start0, &__end0, @@ -41459,7 +41660,7 @@ fn __action651< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action652< +fn __action657< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -41471,7 +41672,7 @@ fn __action652< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action381( + let __temp0 = __action386( mode, __3, ); @@ -41488,7 +41689,7 @@ fn __action652< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action653< +fn __action658< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -41499,7 +41700,7 @@ fn __action653< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action382( + let __temp0 = __action387( mode, &__start0, &__end0, @@ -41517,7 +41718,7 @@ fn __action653< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action654< +fn __action659< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -41528,7 +41729,7 @@ fn __action654< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action381( + let __temp0 = __action386( mode, __2, ); @@ -41544,7 +41745,7 @@ fn __action654< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action655< +fn __action660< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -41554,7 +41755,7 @@ fn __action655< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action382( + let __temp0 = __action387( mode, &__start0, &__end0, @@ -41571,7 +41772,7 @@ fn __action655< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action656< +fn __action661< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41592,7 +41793,7 @@ fn __action656< __1, ); let __temp0 = (__start0, __temp0, __end0); - __action147( + __action149( mode, __0, __temp0, @@ -41608,7 +41809,7 @@ fn __action656< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action657< +fn __action662< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41629,7 +41830,7 @@ fn __action657< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action147( + __action149( mode, __0, __temp0, @@ -41645,7 +41846,7 @@ fn __action657< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action658< +fn __action663< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41653,8 +41854,8 @@ fn __action658< __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Identifier, TextSize), - __5: (TextSize, core::option::Option>, TextSize), - __6: (TextSize, ast::Arguments, TextSize), + __5: (TextSize, core::option::Option, TextSize), + __6: (TextSize, ast::Parameters, TextSize), __7: (TextSize, core::option::Option, TextSize), __8: (TextSize, token::Tok, TextSize), __9: (TextSize, ast::Suite, TextSize), @@ -41667,7 +41868,7 @@ fn __action658< __2, ); let __temp0 = (__start0, __temp0, __end0); - __action161( + __action164( mode, __0, __1, @@ -41684,15 +41885,15 @@ fn __action658< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action659< +fn __action664< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, core::option::Option, TextSize), __7: (TextSize, token::Tok, TextSize), __8: (TextSize, ast::Suite, TextSize), @@ -41706,7 +41907,7 @@ fn __action659< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action161( + __action164( mode, __0, __1, @@ -41723,7 +41924,7 @@ fn __action659< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action660< +fn __action665< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41743,7 +41944,7 @@ fn __action660< __1, ); let __temp0 = (__start0, __temp0, __end0); - __action223( + __action227( mode, __0, __temp0, @@ -41758,7 +41959,7 @@ fn __action660< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action661< +fn __action666< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41778,7 +41979,7 @@ fn __action661< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action223( + __action227( mode, __0, __temp0, @@ -41793,7 +41994,7 @@ fn __action661< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action662< +fn __action667< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41811,7 +42012,7 @@ fn __action662< __1, ); let __temp0 = (__start0, __temp0, __end0); - __action155( + __action157( mode, __0, __temp0, @@ -41824,7 +42025,7 @@ fn __action662< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action663< +fn __action668< >( mode: Mode, __0: (TextSize, TextSize, TextSize), @@ -41842,134 +42043,35 @@ fn __action663< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action155( - mode, - __0, - __temp0, - __1, - __2, - __3, - __4, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action664< ->( - mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ArgumentList, TextSize), - __2: (TextSize, token::Tok, TextSize), -) -> core::option::Option<(token::Tok, ArgumentList, token::Tok)> -{ - let __start0 = __0.0; - let __end0 = __2.2; - let __temp0 = __action268( - mode, - __0, - __1, - __2, - ); - let __temp0 = (__start0, __temp0, __end0); - __action266( - mode, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action665< ->( - mode: Mode, - __0: (TextSize, TextSize, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), - __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ArgumentList, TextSize), - __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt -{ - let __start0 = __5.0; - let __end0 = __7.2; - let __temp0 = __action664( - mode, - __5, - __6, - __7, - ); - let __temp0 = (__start0, __temp0, __end0); - __action170( + __action157( mode, __0, - __1, - __2, - __3, - __4, __temp0, - __8, - __9, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action666< ->( - mode: Mode, - __0: (TextSize, TextSize, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), - __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt -{ - let __start0 = __4.2; - let __end0 = __5.0; - let __temp0 = __action267( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action170( - mode, - __0, __1, __2, __3, __4, - __temp0, - __5, - __6, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action667< +fn __action669< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, Option>, TextSize), -) -> core::option::Option>> + __1: (TextSize, Option>, TextSize), +) -> core::option::Option>> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action411( + let __temp0 = __action418( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action465( + __action468( mode, __temp0, ) @@ -41977,26 +42079,26 @@ fn __action667< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action668< +fn __action670< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, (Vec, Vec), TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action411( + let __temp0 = __action418( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action620( + __action625( mode, __0, __1, @@ -42008,25 +42110,25 @@ fn __action668< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action669< +fn __action671< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, (Vec, Vec), TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action411( + let __temp0 = __action418( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action621( + __action626( mode, __0, __1, @@ -42037,26 +42139,26 @@ fn __action669< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action670< +fn __action672< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __4.0; let __end0 = __5.2; - let __temp0 = __action667( + let __temp0 = __action669( mode, __4, __5, ); let __temp0 = (__start0, __temp0, __end0); - __action416( + __action423( mode, __0, __1, @@ -42068,24 +42170,24 @@ fn __action670< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action671< +fn __action673< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action466( + let __temp0 = __action469( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action416( + __action423( mode, __0, __1, @@ -42097,22 +42199,22 @@ fn __action671< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action672< +fn __action674< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, Option>, TextSize), -) -> core::option::Option>> + __1: (TextSize, Option>, TextSize), +) -> core::option::Option>> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action419( + let __temp0 = __action426( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action454( + __action457( mode, __temp0, ) @@ -42120,26 +42222,26 @@ fn __action672< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action673< +fn __action675< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, (Vec, Vec), TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action419( + let __temp0 = __action426( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action628( + __action633( mode, __0, __1, @@ -42151,25 +42253,25 @@ fn __action673< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action674< +fn __action676< >( mode: Mode, __0: (TextSize, TextSize, TextSize), - __1: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, (Vec, Vec), TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action419( + let __temp0 = __action426( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action629( + __action634( mode, __0, __1, @@ -42180,26 +42282,26 @@ fn __action674< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action675< +fn __action677< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __4.0; let __end0 = __5.2; - let __temp0 = __action672( + let __temp0 = __action674( mode, __4, __5, ); let __temp0 = (__start0, __temp0, __end0); - __action424( + __action431( mode, __0, __1, @@ -42211,24 +42313,24 @@ fn __action675< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action676< +fn __action678< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action455( + let __temp0 = __action458( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action424( + __action431( mode, __0, __1, @@ -42240,22 +42342,22 @@ fn __action676< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action677< +fn __action679< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + __1: (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action469( + let __temp0 = __action472( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action480( + __action487( mode, __temp0, ) @@ -42263,23 +42365,23 @@ fn __action677< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action678< +fn __action680< >( mode: Mode, - __0: (TextSize, alloc::vec::Vec, TextSize), + __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + __2: (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action469( + let __temp0 = __action472( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action481( + __action488( mode, __0, __temp0, @@ -42288,23 +42390,23 @@ fn __action678< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action679< +fn __action681< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> (Vec, Vec) +) -> (Vec, Vec) { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action467( + let __temp0 = __action470( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action418( + __action425( mode, __0, __1, @@ -42315,23 +42417,23 @@ fn __action679< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action680< +fn __action682< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> (Vec, Vec) + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> (Vec, Vec) { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action468( + let __temp0 = __action471( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action418( + __action425( mode, __0, __1, @@ -42342,25 +42444,25 @@ fn __action680< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action681< +fn __action683< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), + __2: (TextSize, core::option::Option, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action467( + let __temp0 = __action470( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action670( + __action672( mode, __0, __1, @@ -42373,25 +42475,25 @@ fn __action681< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action682< +fn __action684< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action468( + let __temp0 = __action471( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action670( + __action672( mode, __0, __1, @@ -42404,23 +42506,23 @@ fn __action682< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action683< +fn __action685< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action467( + let __temp0 = __action470( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action671( + __action673( mode, __0, __1, @@ -42431,23 +42533,23 @@ fn __action683< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action684< +fn __action686< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action468( + let __temp0 = __action471( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action671( + __action673( mode, __0, __1, @@ -42458,22 +42560,22 @@ fn __action684< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action685< +fn __action687< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + __1: (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action458( + let __temp0 = __action461( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action482( + __action489( mode, __temp0, ) @@ -42481,23 +42583,23 @@ fn __action685< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action686< +fn __action688< >( mode: Mode, - __0: (TextSize, alloc::vec::Vec, TextSize), + __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::ArgWithDefault, TextSize), -) -> alloc::vec::Vec + __2: (TextSize, ast::ParameterWithDefault, TextSize), +) -> alloc::vec::Vec { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action458( + let __temp0 = __action461( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action483( + __action490( mode, __0, __temp0, @@ -42506,23 +42608,23 @@ fn __action686< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action687< +fn __action689< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> (Vec, Vec) +) -> (Vec, Vec) { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action456( + let __temp0 = __action459( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action426( + __action433( mode, __0, __1, @@ -42533,23 +42635,23 @@ fn __action687< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action688< +fn __action690< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> (Vec, Vec) + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> (Vec, Vec) { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action457( + let __temp0 = __action460( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action426( + __action433( mode, __0, __1, @@ -42560,25 +42662,25 @@ fn __action688< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action689< +fn __action691< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), + __2: (TextSize, core::option::Option, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action456( + let __temp0 = __action459( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action675( + __action677( mode, __0, __1, @@ -42591,25 +42693,25 @@ fn __action689< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action690< +fn __action692< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action457( + let __temp0 = __action460( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action675( + __action677( mode, __0, __1, @@ -42622,23 +42724,23 @@ fn __action690< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action691< +fn __action693< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action456( + let __temp0 = __action459( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action676( + __action678( mode, __0, __1, @@ -42649,23 +42751,23 @@ fn __action691< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action692< +fn __action694< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, core::option::Option, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action457( + let __temp0 = __action460( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action676( + __action678( mode, __0, __1, @@ -42676,24 +42778,24 @@ fn __action692< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action693< +fn __action695< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), + __2: (TextSize, ast::Parameter, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action472( + let __temp0 = __action475( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action681( + __action683( mode, __0, __1, @@ -42705,24 +42807,24 @@ fn __action693< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action694< +fn __action696< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action473( + let __temp0 = __action476( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action681( + __action683( mode, __0, __1, @@ -42734,25 +42836,25 @@ fn __action694< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action695< +fn __action697< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action472( + let __temp0 = __action475( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action682( + __action684( mode, __0, __1, @@ -42765,25 +42867,25 @@ fn __action695< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action696< +fn __action698< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action473( + let __temp0 = __action476( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action682( + __action684( mode, __0, __1, @@ -42796,22 +42898,22 @@ fn __action696< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action697< +fn __action699< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action472( + let __temp0 = __action475( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action683( + __action685( mode, __0, __1, @@ -42821,22 +42923,22 @@ fn __action697< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action698< +fn __action700< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action473( + let __temp0 = __action476( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action683( + __action685( mode, __0, __1, @@ -42846,23 +42948,23 @@ fn __action698< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action699< +fn __action701< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action472( + let __temp0 = __action475( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action684( + __action686( mode, __0, __1, @@ -42873,23 +42975,23 @@ fn __action699< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action700< +fn __action702< >( mode: Mode, __0: (TextSize, TextSize, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action473( + let __temp0 = __action476( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action684( + __action686( mode, __0, __1, @@ -42900,7 +43002,7 @@ fn __action700< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action701< +fn __action703< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -42911,7 +43013,7 @@ fn __action701< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -42929,7 +43031,7 @@ fn __action701< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action702< +fn __action704< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -42939,7 +43041,7 @@ fn __action702< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -42956,7 +43058,7 @@ fn __action702< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action703< +fn __action705< >( mode: Mode, __0: (TextSize, (String, StringKind, bool), TextSize), @@ -42965,7 +43067,7 @@ fn __action703< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -42981,7 +43083,7 @@ fn __action703< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action704< +fn __action706< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -42992,13 +43094,13 @@ fn __action704< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action112( + __action114( mode, __temp0, __0, @@ -43010,7 +43112,7 @@ fn __action704< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action705< +fn __action707< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -43021,13 +43123,13 @@ fn __action705< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action450( + __action481( mode, __temp0, __0, @@ -43039,7 +43141,7 @@ fn __action705< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action706< +fn __action708< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -43050,13 +43152,13 @@ fn __action706< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action509( + __action512( mode, __temp0, __0, @@ -43068,7 +43170,7 @@ fn __action706< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action707< +fn __action709< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -43078,13 +43180,13 @@ fn __action707< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action434( + __action439( mode, __temp0, __0, @@ -43095,7 +43197,7 @@ fn __action707< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action708< +fn __action710< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -43105,13 +43207,13 @@ fn __action708< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action478( + __action485( mode, __temp0, __0, @@ -43122,7 +43224,36 @@ fn __action708< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action709< +fn __action711< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), + __2: (TextSize, token::Tok, TextSize), + __3: (TextSize, TextSize, TextSize), +) -> Result> +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __temp0 = __action395( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action230( + mode, + __temp0, + __0, + __1, + __2, + __3, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action712< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -43133,13 +43264,13 @@ fn __action709< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action491( + __action498( mode, __temp0, __0, @@ -43151,7 +43282,7 @@ fn __action709< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action710< +fn __action713< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -43162,13 +43293,13 @@ fn __action710< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action536( + __action522( mode, __temp0, __0, @@ -43180,7 +43311,7 @@ fn __action710< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action711< +fn __action714< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -43191,13 +43322,13 @@ fn __action711< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action93( + __action95( mode, __temp0, __0, @@ -43209,7 +43340,7 @@ fn __action711< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action712< +fn __action715< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43220,13 +43351,13 @@ fn __action712< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action72( + __action73( mode, __temp0, __0, @@ -43238,7 +43369,7 @@ fn __action712< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action713< +fn __action716< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -43246,13 +43377,13 @@ fn __action713< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action517( + __action524( mode, __temp0, __0, @@ -43261,7 +43392,7 @@ fn __action713< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action714< +fn __action717< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -43270,13 +43401,13 @@ fn __action714< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action518( + __action525( mode, __temp0, __0, @@ -43286,7 +43417,7 @@ fn __action714< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action715< +fn __action718< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -43295,13 +43426,13 @@ fn __action715< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action519( + __action526( mode, __temp0, __0, @@ -43311,7 +43442,7 @@ fn __action715< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action716< +fn __action719< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43322,13 +43453,13 @@ fn __action716< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action520( + __action527( mode, __temp0, __0, @@ -43340,7 +43471,7 @@ fn __action716< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action717< +fn __action720< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43352,13 +43483,13 @@ fn __action717< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action521( + __action528( mode, __temp0, __0, @@ -43371,7 +43502,7 @@ fn __action717< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action718< +fn __action721< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43383,13 +43514,13 @@ fn __action718< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action580( + __action585( mode, __temp0, __0, @@ -43402,7 +43533,7 @@ fn __action718< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action719< +fn __action722< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43413,13 +43544,13 @@ fn __action719< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action581( + __action586( mode, __temp0, __0, @@ -43431,7 +43562,7 @@ fn __action719< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action720< +fn __action723< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43445,13 +43576,13 @@ fn __action720< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action582( + __action587( mode, __temp0, __0, @@ -43466,7 +43597,7 @@ fn __action720< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action721< +fn __action724< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43479,13 +43610,13 @@ fn __action721< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action583( + __action588( mode, __temp0, __0, @@ -43499,7 +43630,7 @@ fn __action721< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action722< +fn __action725< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43509,13 +43640,13 @@ fn __action722< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action524( + __action531( mode, __temp0, __0, @@ -43526,7 +43657,7 @@ fn __action722< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action723< +fn __action726< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43538,13 +43669,13 @@ fn __action723< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action526( + __action533( mode, __temp0, __0, @@ -43557,7 +43688,7 @@ fn __action723< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action724< +fn __action727< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43569,13 +43700,13 @@ fn __action724< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action527( + __action534( mode, __0, __temp0, @@ -43588,7 +43719,7 @@ fn __action724< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action725< +fn __action728< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43599,13 +43730,13 @@ fn __action725< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action528( + __action535( mode, __temp0, __0, @@ -43617,7 +43748,7 @@ fn __action725< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action726< +fn __action729< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43629,13 +43760,13 @@ fn __action726< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action529( + __action536( mode, __temp0, __0, @@ -43648,7 +43779,7 @@ fn __action726< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action727< +fn __action730< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43659,13 +43790,13 @@ fn __action727< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action530( + __action537( mode, __temp0, __0, @@ -43677,7 +43808,7 @@ fn __action727< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action728< +fn __action731< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43689,13 +43820,13 @@ fn __action728< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action531( + __action538( mode, __temp0, __0, @@ -43708,7 +43839,7 @@ fn __action728< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action729< +fn __action732< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43717,13 +43848,13 @@ fn __action729< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action532( + __action539( mode, __temp0, __0, @@ -43733,7 +43864,7 @@ fn __action729< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action730< +fn __action733< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43742,13 +43873,13 @@ fn __action730< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action533( + __action540( mode, __temp0, __0, @@ -43758,7 +43889,7 @@ fn __action730< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action731< +fn __action734< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43767,13 +43898,13 @@ fn __action731< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action534( + __action541( mode, __temp0, __0, @@ -43783,7 +43914,7 @@ fn __action731< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action732< +fn __action735< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43792,13 +43923,13 @@ fn __action732< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action535( + __action542( mode, __temp0, __0, @@ -43808,7 +43939,7 @@ fn __action732< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action733< +fn __action736< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -43816,13 +43947,13 @@ fn __action733< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action562( + __action567( mode, __temp0, __0, @@ -43831,7 +43962,7 @@ fn __action733< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action734< +fn __action737< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -43840,13 +43971,13 @@ fn __action734< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action563( + __action568( mode, __temp0, __0, @@ -43856,7 +43987,7 @@ fn __action734< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action735< +fn __action738< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -43865,13 +43996,13 @@ fn __action735< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action564( + __action569( mode, __temp0, __0, @@ -43881,7 +44012,7 @@ fn __action735< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action736< +fn __action739< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43892,13 +44023,13 @@ fn __action736< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action565( + __action570( mode, __temp0, __0, @@ -43910,7 +44041,7 @@ fn __action736< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action737< +fn __action740< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43922,13 +44053,13 @@ fn __action737< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action566( + __action571( mode, __temp0, __0, @@ -43941,7 +44072,7 @@ fn __action737< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action738< +fn __action741< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43955,13 +44086,13 @@ fn __action738< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action584( + __action589( mode, __temp0, __0, @@ -43976,7 +44107,7 @@ fn __action738< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action739< +fn __action742< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -43989,13 +44120,13 @@ fn __action739< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action585( + __action590( mode, __temp0, __0, @@ -44009,7 +44140,7 @@ fn __action739< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action740< +fn __action743< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44019,13 +44150,13 @@ fn __action740< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action568( + __action573( mode, __temp0, __0, @@ -44036,7 +44167,7 @@ fn __action740< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action741< +fn __action744< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44048,13 +44179,13 @@ fn __action741< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action570( + __action575( mode, __temp0, __0, @@ -44067,7 +44198,7 @@ fn __action741< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action742< +fn __action745< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44079,13 +44210,13 @@ fn __action742< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action571( + __action576( mode, __0, __temp0, @@ -44098,7 +44229,7 @@ fn __action742< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action743< +fn __action746< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44109,13 +44240,13 @@ fn __action743< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action572( + __action577( mode, __temp0, __0, @@ -44127,7 +44258,7 @@ fn __action743< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action744< +fn __action747< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44139,13 +44270,13 @@ fn __action744< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action573( + __action578( mode, __temp0, __0, @@ -44158,7 +44289,7 @@ fn __action744< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action745< +fn __action748< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44169,13 +44300,13 @@ fn __action745< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action574( + __action579( mode, __temp0, __0, @@ -44187,7 +44318,7 @@ fn __action745< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action746< +fn __action749< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44199,13 +44330,13 @@ fn __action746< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action575( + __action580( mode, __temp0, __0, @@ -44218,7 +44349,7 @@ fn __action746< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action747< +fn __action750< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44227,13 +44358,13 @@ fn __action747< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action576( + __action581( mode, __temp0, __0, @@ -44243,7 +44374,7 @@ fn __action747< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action748< +fn __action751< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44252,13 +44383,13 @@ fn __action748< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action577( + __action582( mode, __temp0, __0, @@ -44268,7 +44399,7 @@ fn __action748< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action749< +fn __action752< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44277,13 +44408,13 @@ fn __action749< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action578( + __action583( mode, __temp0, __0, @@ -44293,7 +44424,7 @@ fn __action749< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action750< +fn __action753< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -44302,108 +44433,17 @@ fn __action750< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action579( - mode, - __temp0, - __0, - __1, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action751< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ArgumentList, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - let __start0 = __0.0; - let __end0 = __0.0; - let __temp0 = __action390( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action514( - mode, - __temp0, - __0, - __1, - __2, - __3, - __4, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action752< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Expr, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - let __start0 = __0.0; - let __end0 = __0.0; - let __temp0 = __action390( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action515( - mode, - __temp0, - __0, - __1, - __2, - __3, - __4, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action753< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, TextSize, TextSize), -) -> ast::Expr -{ - let __start0 = __0.0; - let __end0 = __0.0; - let __temp0 = __action390( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action516( + __action584( mode, __temp0, __0, __1, - __2, - __3, ) } @@ -44413,28 +44453,24 @@ fn __action754< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ArgumentList, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, TextSize, TextSize), + __1: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, TextSize, TextSize), ) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action559( + __action517( mode, __temp0, __0, __1, __2, - __3, - __4, ) } @@ -44452,13 +44488,13 @@ fn __action755< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action560( + __action518( mode, __temp0, __0, @@ -44482,13 +44518,13 @@ fn __action756< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action561( + __action519( mode, __temp0, __0, @@ -44503,20 +44539,20 @@ fn __action756< fn __action757< >( mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Expr, TextSize), + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, ast::Arguments, TextSize), __2: (TextSize, TextSize, TextSize), ) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action507( + __action564( mode, __temp0, __0, @@ -44530,25 +44566,29 @@ fn __action757< fn __action758< >( mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Expr, TextSize), - __2: (TextSize, TextSize, TextSize), + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Expr, TextSize), + __3: (TextSize, token::Tok, TextSize), + __4: (TextSize, TextSize, TextSize), ) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action556( + __action565( mode, __temp0, __0, __1, __2, + __3, + __4, ) } @@ -44557,23 +44597,27 @@ fn __action758< fn __action759< >( mode: Mode, - __0: (TextSize, ast::Identifier, TextSize), - __1: (TextSize, TextSize, TextSize), -) -> ast::Pattern + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Identifier, TextSize), + __3: (TextSize, TextSize, TextSize), +) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action119( + __action566( mode, __temp0, __0, __1, + __2, + __3, ) } @@ -44582,62 +44626,103 @@ fn __action759< fn __action760< >( mode: Mode, - __0: (TextSize, alloc::vec::Vec, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ArgumentList, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, ast::Expr, TextSize), + __2: (TextSize, TextSize, TextSize), +) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action665( + __action514( mode, __temp0, __0, __1, __2, - __3, - __4, - __5, - __6, - __7, - __8, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] fn __action761< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, ast::Expr, TextSize), + __2: (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __temp0 = __action395( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action561( + mode, + __temp0, + __0, + __1, + __2, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action762< +>( + mode: Mode, + __0: (TextSize, ast::Identifier, TextSize), + __1: (TextSize, TextSize, TextSize), +) -> ast::Pattern +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __temp0 = __action395( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action121( + mode, + __temp0, + __0, + __1, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action763< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Suite, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action666( + __action173( mode, __temp0, __0, @@ -44646,12 +44731,13 @@ fn __action761< __3, __4, __5, + __6, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action762< +fn __action764< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44666,13 +44752,13 @@ fn __action762< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action586( + __action591( mode, __temp0, __0, @@ -44688,7 +44774,7 @@ fn __action762< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action763< +fn __action765< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44702,13 +44788,13 @@ fn __action763< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action587( + __action592( mode, __temp0, __0, @@ -44723,7 +44809,7 @@ fn __action763< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action764< +fn __action766< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44736,13 +44822,13 @@ fn __action764< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action588( + __action593( mode, __temp0, __0, @@ -44756,7 +44842,7 @@ fn __action764< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action765< +fn __action767< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44768,13 +44854,13 @@ fn __action765< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action589( + __action594( mode, __temp0, __0, @@ -44787,7 +44873,7 @@ fn __action765< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action766< +fn __action768< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44800,13 +44886,13 @@ fn __action766< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action590( + __action595( mode, __temp0, __0, @@ -44820,7 +44906,7 @@ fn __action766< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action767< +fn __action769< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44832,13 +44918,13 @@ fn __action767< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action591( + __action596( mode, __temp0, __0, @@ -44851,7 +44937,7 @@ fn __action767< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action768< +fn __action770< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44862,13 +44948,13 @@ fn __action768< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action140( + __action142( mode, __temp0, __0, @@ -44880,7 +44966,7 @@ fn __action768< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action769< +fn __action771< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44895,13 +44981,13 @@ fn __action769< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action592( + __action597( mode, __temp0, __0, @@ -44917,7 +45003,7 @@ fn __action769< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action770< +fn __action772< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44931,13 +45017,13 @@ fn __action770< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action593( + __action598( mode, __temp0, __0, @@ -44952,7 +45038,7 @@ fn __action770< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action771< +fn __action773< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44965,13 +45051,13 @@ fn __action771< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action594( + __action599( mode, __temp0, __0, @@ -44985,7 +45071,7 @@ fn __action771< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action772< +fn __action774< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -44997,13 +45083,13 @@ fn __action772< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action595( + __action600( mode, __temp0, __0, @@ -45016,7 +45102,7 @@ fn __action772< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action773< +fn __action775< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45029,13 +45115,13 @@ fn __action773< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action596( + __action601( mode, __temp0, __0, @@ -45049,7 +45135,7 @@ fn __action773< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action774< +fn __action776< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45061,13 +45147,13 @@ fn __action774< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action597( + __action602( mode, __temp0, __0, @@ -45080,7 +45166,7 @@ fn __action774< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action775< +fn __action777< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45091,13 +45177,13 @@ fn __action775< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action144( + __action146( mode, __temp0, __0, @@ -45109,7 +45195,7 @@ fn __action775< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action776< +fn __action778< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45119,13 +45205,13 @@ fn __action776< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action486( + __action491( mode, __temp0, __0, @@ -45136,7 +45222,7 @@ fn __action776< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action777< +fn __action779< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45146,13 +45232,13 @@ fn __action777< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action495( + __action502( mode, __temp0, __0, @@ -45163,7 +45249,7 @@ fn __action777< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action778< +fn __action780< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -45172,13 +45258,13 @@ fn __action778< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action109( + __action111( mode, __temp0, __0, @@ -45188,7 +45274,7 @@ fn __action778< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action779< +fn __action781< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45198,13 +45284,13 @@ fn __action779< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action111( + __action113( mode, __temp0, __0, @@ -45215,7 +45301,7 @@ fn __action779< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action780< +fn __action782< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45226,13 +45312,13 @@ fn __action780< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action175( + __action178( mode, __temp0, __0, @@ -45244,7 +45330,7 @@ fn __action780< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action781< +fn __action783< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45254,13 +45340,13 @@ fn __action781< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action24( + __action25( mode, __temp0, __0, @@ -45271,7 +45357,7 @@ fn __action781< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action782< +fn __action784< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -45280,13 +45366,13 @@ fn __action782< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action68( + __action69( mode, __temp0, __0, @@ -45296,7 +45382,7 @@ fn __action782< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action783< +fn __action785< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -45306,13 +45392,13 @@ fn __action783< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action69( + __action70( mode, __temp0, __0, @@ -45323,23 +45409,23 @@ fn __action783< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action784< +fn __action786< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action169( + __action172( mode, __temp0, __0, @@ -45350,7 +45436,7 @@ fn __action784< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action785< +fn __action787< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45361,13 +45447,13 @@ fn __action785< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action153( + __action155( mode, __temp0, __0, @@ -45379,7 +45465,7 @@ fn __action785< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action786< +fn __action788< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45390,13 +45476,13 @@ fn __action786< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action154( + __action156( mode, __temp0, __0, @@ -45408,7 +45494,7 @@ fn __action786< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action787< +fn __action789< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45420,13 +45506,13 @@ fn __action787< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action151( + __action153( mode, __temp0, __0, @@ -45439,7 +45525,7 @@ fn __action787< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action788< +fn __action790< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45451,13 +45537,13 @@ fn __action788< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action152( + __action154( mode, __temp0, __0, @@ -45470,7 +45556,7 @@ fn __action788< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action789< +fn __action791< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45481,13 +45567,13 @@ fn __action789< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action248( + __action352( mode, __temp0, __0, @@ -45499,7 +45585,7 @@ fn __action789< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action790< +fn __action792< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45510,13 +45596,13 @@ fn __action790< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action501( + __action504( mode, __temp0, __0, @@ -45528,7 +45614,7 @@ fn __action790< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action791< +fn __action793< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45538,13 +45624,13 @@ fn __action791< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action25( + __action26( mode, __temp0, __0, @@ -45555,7 +45641,7 @@ fn __action791< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action792< +fn __action794< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45566,13 +45652,13 @@ fn __action792< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action26( + __action27( mode, __temp0, __0, @@ -45584,7 +45670,7 @@ fn __action792< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action793< +fn __action795< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45596,13 +45682,13 @@ fn __action793< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action27( + __action28( mode, __temp0, __0, @@ -45615,7 +45701,7 @@ fn __action793< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action794< +fn __action796< >( mode: Mode, __0: (TextSize, ast::UnaryOp, TextSize), @@ -45625,13 +45711,13 @@ fn __action794< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action499( + __action506( mode, __temp0, __0, @@ -45642,7 +45728,7 @@ fn __action794< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action795< +fn __action797< >( mode: Mode, __0: (TextSize, ast::UnaryOp, TextSize), @@ -45652,13 +45738,13 @@ fn __action795< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action552( + __action555( mode, __temp0, __0, @@ -45669,7 +45755,7 @@ fn __action795< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action796< +fn __action798< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45678,13 +45764,13 @@ fn __action796< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action52( + __action53( mode, __temp0, __0, @@ -45694,7 +45780,7 @@ fn __action796< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action797< +fn __action799< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45703,13 +45789,13 @@ fn __action797< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action53( + __action54( mode, __temp0, __0, @@ -45719,7 +45805,7 @@ fn __action797< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action798< +fn __action800< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45729,13 +45815,13 @@ fn __action798< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action54( + __action55( mode, __temp0, __0, @@ -45746,7 +45832,7 @@ fn __action798< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action799< +fn __action801< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45755,13 +45841,13 @@ fn __action799< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action55( + __action56( mode, __temp0, __0, @@ -45771,7 +45857,7 @@ fn __action799< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action800< +fn __action802< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45786,13 +45872,13 @@ fn __action800< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action656( + __action661( mode, __temp0, __0, @@ -45808,7 +45894,7 @@ fn __action800< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action801< +fn __action803< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45822,13 +45908,13 @@ fn __action801< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action657( + __action662( mode, __temp0, __0, @@ -45843,15 +45929,15 @@ fn __action801< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action802< +fn __action804< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, core::option::Option, TextSize), __7: (TextSize, token::Tok, TextSize), __8: (TextSize, ast::Suite, TextSize), @@ -45859,13 +45945,13 @@ fn __action802< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action658( + __action663( mode, __temp0, __0, @@ -45882,14 +45968,14 @@ fn __action802< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action803< +fn __action805< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, core::option::Option, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Suite, TextSize), @@ -45897,13 +45983,13 @@ fn __action803< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action659( + __action664( mode, __temp0, __0, @@ -45919,7 +46005,7 @@ fn __action803< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action804< +fn __action806< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -45929,13 +46015,13 @@ fn __action804< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action227( + __action231( mode, __temp0, __0, @@ -45946,7 +46032,7 @@ fn __action804< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action805< +fn __action807< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -45957,13 +46043,13 @@ fn __action805< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action228( + __action232( mode, __temp0, __0, @@ -45975,7 +46061,7 @@ fn __action805< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action806< +fn __action808< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -45985,13 +46071,13 @@ fn __action806< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action229( + __action233( mode, __temp0, __0, @@ -46002,7 +46088,7 @@ fn __action806< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action807< +fn __action809< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46012,13 +46098,13 @@ fn __action807< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action230( + __action234( mode, __temp0, __0, @@ -46029,7 +46115,7 @@ fn __action807< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action808< +fn __action810< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -46039,13 +46125,13 @@ fn __action808< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action602( + __action607( mode, __temp0, __0, @@ -46056,7 +46142,7 @@ fn __action808< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action809< +fn __action811< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -46065,13 +46151,13 @@ fn __action809< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action603( + __action608( mode, __temp0, __0, @@ -46081,7 +46167,7 @@ fn __action809< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action810< +fn __action812< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -46091,13 +46177,13 @@ fn __action810< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action604( + __action609( mode, __temp0, __0, @@ -46108,7 +46194,7 @@ fn __action810< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action811< +fn __action813< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -46117,13 +46203,13 @@ fn __action811< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action605( + __action610( mode, __temp0, __0, @@ -46133,7 +46219,7 @@ fn __action811< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action812< +fn __action814< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46143,13 +46229,13 @@ fn __action812< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action70( + __action71( mode, __temp0, __0, @@ -46160,7 +46246,7 @@ fn __action812< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action813< +fn __action815< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -46169,13 +46255,13 @@ fn __action813< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action234( + __action238( mode, __temp0, __0, @@ -46185,7 +46271,7 @@ fn __action813< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action814< +fn __action816< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46198,13 +46284,13 @@ fn __action814< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action145( + __action147( mode, __temp0, __0, @@ -46218,7 +46304,7 @@ fn __action814< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action815< +fn __action817< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -46228,13 +46314,13 @@ fn __action815< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action368( + __action373( mode, __temp0, __0, @@ -46245,7 +46331,7 @@ fn __action815< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action816< +fn __action818< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -46255,13 +46341,13 @@ fn __action816< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action361( + __action366( mode, __temp0, __0, @@ -46272,7 +46358,7 @@ fn __action816< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action817< +fn __action819< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -46281,13 +46367,13 @@ fn __action817< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action65( + __action66( mode, __temp0, __0, @@ -46297,7 +46383,7 @@ fn __action817< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action818< +fn __action820< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46309,13 +46395,13 @@ fn __action818< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action606( + __action611( mode, __temp0, __0, @@ -46328,7 +46414,7 @@ fn __action818< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action819< +fn __action821< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46339,13 +46425,13 @@ fn __action819< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action607( + __action612( mode, __temp0, __0, @@ -46357,7 +46443,7 @@ fn __action819< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action820< +fn __action822< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46366,13 +46452,13 @@ fn __action820< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action67( + __action68( mode, __temp0, __0, @@ -46382,7 +46468,7 @@ fn __action820< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action821< +fn __action823< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46392,13 +46478,13 @@ fn __action821< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action59( + __action60( mode, __temp0, __0, @@ -46409,7 +46495,7 @@ fn __action821< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action822< +fn __action824< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46421,13 +46507,13 @@ fn __action822< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action60( + __action61( mode, __temp0, __0, @@ -46440,58 +46526,41 @@ fn __action822< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action823< +fn __action825< >( mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), - __2: (TextSize, TextSize, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, ast::Expr, TextSize), - __5: (TextSize, TextSize, TextSize), + __0: (TextSize, (IpyEscapeKind, String), TextSize), + __1: (TextSize, TextSize, TextSize), ) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __start1 = __0.2; - let __end1 = __1.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - let __temp1 = __action390( - mode, - &__start1, - &__end1, - ); - let __temp1 = (__start1, __temp1, __end1); - __action181( + __action75( mode, __temp0, __0, - __temp1, __1, - __2, - __3, - __4, - __5, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action824< +fn __action826< >( mode: Mode, - __0: (TextSize, (MagicKind, String), TextSize), + __0: (TextSize, (IpyEscapeKind, String), TextSize), __1: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -46507,32 +46576,76 @@ fn __action824< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action825< +fn __action827< >( mode: Mode, - __0: (TextSize, (MagicKind, String), TextSize), - __1: (TextSize, TextSize, TextSize), + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, TextSize, TextSize), ) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action73( + __action76( mode, __temp0, __0, __1, + __2, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action826< +fn __action828< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, core::option::Option, TextSize), + __2: (TextSize, TextSize, TextSize), + __3: (TextSize, token::Tok, TextSize), + __4: (TextSize, ast::Expr, TextSize), + __5: (TextSize, TextSize, TextSize), +) -> Result> +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __start1 = __0.2; + let __end1 = __1.0; + let __temp0 = __action395( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + let __temp1 = __action395( + mode, + &__start1, + &__end1, + ); + let __temp1 = (__start1, __temp1, __end1); + __action185( + mode, + __temp0, + __0, + __temp1, + __1, + __2, + __3, + __4, + __5, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action829< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46541,13 +46654,13 @@ fn __action826< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action113( + __action115( mode, __temp0, __0, @@ -46557,7 +46670,7 @@ fn __action826< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action827< +fn __action830< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46566,13 +46679,13 @@ fn __action827< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action114( + __action116( mode, __temp0, __0, @@ -46582,7 +46695,7 @@ fn __action827< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action828< +fn __action831< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46591,13 +46704,13 @@ fn __action828< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action115( + __action117( mode, __temp0, __0, @@ -46607,7 +46720,7 @@ fn __action828< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action829< +fn __action832< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -46616,13 +46729,13 @@ fn __action829< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action116( + __action118( mode, __temp0, __0, @@ -46632,7 +46745,7 @@ fn __action829< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action830< +fn __action833< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -46641,13 +46754,13 @@ fn __action830< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action117( + __action119( mode, __temp0, __0, @@ -46657,7 +46770,7 @@ fn __action830< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action831< +fn __action834< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -46666,13 +46779,13 @@ fn __action831< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action118( + __action120( mode, __temp0, __0, @@ -46682,7 +46795,7 @@ fn __action831< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action832< +fn __action835< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46691,13 +46804,13 @@ fn __action832< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action127( + __action129( mode, __temp0, __0, @@ -46707,7 +46820,7 @@ fn __action832< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action833< +fn __action836< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46716,13 +46829,13 @@ fn __action833< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action128( + __action130( mode, __temp0, __0, @@ -46732,7 +46845,7 @@ fn __action833< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action834< +fn __action837< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46741,13 +46854,13 @@ fn __action834< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action129( + __action131( mode, __temp0, __0, @@ -46757,7 +46870,7 @@ fn __action834< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action835< +fn __action838< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -46765,13 +46878,13 @@ fn __action835< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action130( + __action132( mode, __temp0, __0, @@ -46780,7 +46893,7 @@ fn __action835< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action836< +fn __action839< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46790,13 +46903,13 @@ fn __action836< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action132( + __action134( mode, __temp0, __0, @@ -46807,7 +46920,7 @@ fn __action836< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action837< +fn __action840< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46819,13 +46932,13 @@ fn __action837< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action610( + __action615( mode, __temp0, __0, @@ -46838,7 +46951,7 @@ fn __action837< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action838< +fn __action841< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46849,13 +46962,13 @@ fn __action838< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action611( + __action616( mode, __temp0, __0, @@ -46867,7 +46980,7 @@ fn __action838< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action839< +fn __action842< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46880,13 +46993,13 @@ fn __action839< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action612( + __action617( mode, __temp0, __0, @@ -46900,7 +47013,7 @@ fn __action839< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action840< +fn __action843< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46912,13 +47025,13 @@ fn __action840< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action613( + __action618( mode, __temp0, __0, @@ -46931,7 +47044,7 @@ fn __action840< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action841< +fn __action844< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46946,13 +47059,13 @@ fn __action841< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action614( + __action619( mode, __temp0, __0, @@ -46968,7 +47081,7 @@ fn __action841< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action842< +fn __action845< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -46982,13 +47095,13 @@ fn __action842< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action615( + __action620( mode, __temp0, __0, @@ -47003,7 +47116,7 @@ fn __action842< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action843< +fn __action846< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47015,13 +47128,13 @@ fn __action843< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action86( + __action88( mode, __temp0, __0, @@ -47034,7 +47147,7 @@ fn __action843< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action844< +fn __action847< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -47043,13 +47156,13 @@ fn __action844< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action120( + __action122( mode, __temp0, __0, @@ -47059,7 +47172,7 @@ fn __action844< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action845< +fn __action848< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -47070,13 +47183,13 @@ fn __action845< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action121( + __action123( mode, __temp0, __0, @@ -47088,7 +47201,7 @@ fn __action845< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action846< +fn __action849< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -47099,13 +47212,13 @@ fn __action846< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action122( + __action124( mode, __temp0, __0, @@ -47117,7 +47230,7 @@ fn __action846< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action847< +fn __action850< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47131,13 +47244,13 @@ fn __action847< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action83( + __action85( mode, __temp0, __0, @@ -47152,7 +47265,7 @@ fn __action847< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action848< +fn __action851< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47167,13 +47280,13 @@ fn __action848< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action84( + __action86( mode, __temp0, __0, @@ -47189,7 +47302,7 @@ fn __action848< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action849< +fn __action852< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47204,13 +47317,13 @@ fn __action849< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action616( + __action621( mode, __temp0, __0, @@ -47226,7 +47339,7 @@ fn __action849< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action850< +fn __action853< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47240,13 +47353,13 @@ fn __action850< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action617( + __action622( mode, __temp0, __0, @@ -47261,24 +47374,24 @@ fn __action850< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action851< +fn __action854< >( mode: Mode, - __0: (TextSize, ast::Identifier, TextSize), - __1: (TextSize, TextSize, TextSize), - __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Expr, TextSize), + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Expr, TextSize), + __3: (TextSize, TextSize, TextSize), ) -> ast::Expr { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action180( + __action184( mode, __temp0, __0, @@ -47290,7 +47403,32 @@ fn __action851< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action852< +fn __action855< +>( + mode: Mode, + __0: (TextSize, ast::Identifier, TextSize), + __1: (TextSize, TextSize, TextSize), +) -> ast::Expr +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __temp0 = __action395( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action183( + mode, + __temp0, + __0, + __1, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action856< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47300,13 +47438,13 @@ fn __action852< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action71( + __action72( mode, __temp0, __0, @@ -47317,7 +47455,7 @@ fn __action852< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action853< +fn __action857< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47327,13 +47465,13 @@ fn __action853< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action448( + __action453( mode, __temp0, __0, @@ -47344,7 +47482,7 @@ fn __action853< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action854< +fn __action858< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -47354,13 +47492,13 @@ fn __action854< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action493( + __action496( mode, __temp0, __0, @@ -47371,7 +47509,7 @@ fn __action854< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action855< +fn __action859< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -47380,13 +47518,13 @@ fn __action855< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action95( + __action97( mode, __temp0, __0, @@ -47396,7 +47534,7 @@ fn __action855< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action856< +fn __action860< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -47406,13 +47544,13 @@ fn __action856< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action240( + __action244( mode, __temp0, __0, @@ -47423,7 +47561,7 @@ fn __action856< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action857< +fn __action861< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -47433,13 +47571,13 @@ fn __action857< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action476( + __action479( mode, __temp0, __0, @@ -47450,24 +47588,24 @@ fn __action857< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action858< +fn __action862< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), - __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __0: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action618( + __action623( mode, __temp0, __0, @@ -47479,23 +47617,23 @@ fn __action858< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action859< +fn __action863< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), - __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __0: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action619( + __action624( mode, __temp0, __0, @@ -47506,25 +47644,25 @@ fn __action859< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action860< +fn __action864< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action668( + __action670( mode, __temp0, __0, @@ -47537,24 +47675,24 @@ fn __action860< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action861< +fn __action865< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action669( + __action671( mode, __temp0, __0, @@ -47566,23 +47704,23 @@ fn __action861< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action862< +fn __action866< >( mode: Mode, - __0: (TextSize, (Option>, Vec, Option>), TextSize), + __0: (TextSize, (Option>, Vec, Option>), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action622( + __action627( mode, __temp0, __0, @@ -47593,22 +47731,22 @@ fn __action862< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action863< +fn __action867< >( mode: Mode, - __0: (TextSize, (Option>, Vec, Option>), TextSize), + __0: (TextSize, (Option>, Vec, Option>), TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action623( + __action628( mode, __temp0, __0, @@ -47618,23 +47756,23 @@ fn __action863< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action864< +fn __action868< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action624( + __action629( mode, __temp0, __0, @@ -47645,22 +47783,22 @@ fn __action864< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action865< +fn __action869< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action625( + __action630( mode, __temp0, __0, @@ -47670,24 +47808,24 @@ fn __action865< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action866< +fn __action870< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), - __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __0: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action626( + __action631( mode, __temp0, __0, @@ -47699,23 +47837,23 @@ fn __action866< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action867< +fn __action871< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), - __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), + __0: (TextSize, (Vec, Vec), TextSize), + __1: (TextSize, core::option::Option<(Option>, Vec, Option>)>, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action627( + __action632( mode, __temp0, __0, @@ -47726,25 +47864,25 @@ fn __action867< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action868< +fn __action872< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action673( + __action675( mode, __temp0, __0, @@ -47757,24 +47895,24 @@ fn __action868< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action869< +fn __action873< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action674( + __action676( mode, __temp0, __0, @@ -47786,23 +47924,23 @@ fn __action869< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action870< +fn __action874< >( mode: Mode, - __0: (TextSize, (Option>, Vec, Option>), TextSize), + __0: (TextSize, (Option>, Vec, Option>), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action630( + __action635( mode, __temp0, __0, @@ -47813,22 +47951,22 @@ fn __action870< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action871< +fn __action875< >( mode: Mode, - __0: (TextSize, (Option>, Vec, Option>), TextSize), + __0: (TextSize, (Option>, Vec, Option>), TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action631( + __action636( mode, __temp0, __0, @@ -47838,23 +47976,23 @@ fn __action871< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action872< +fn __action876< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action632( + __action637( mode, __temp0, __0, @@ -47865,22 +48003,22 @@ fn __action872< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action873< +fn __action877< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action633( + __action638( mode, __temp0, __0, @@ -47890,24 +48028,24 @@ fn __action873< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action874< +fn __action878< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action693( + __action695( mode, __temp0, __0, @@ -47919,23 +48057,23 @@ fn __action874< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action875< +fn __action879< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action694( + __action696( mode, __temp0, __0, @@ -47946,25 +48084,25 @@ fn __action875< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action876< +fn __action880< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action695( + __action697( mode, __temp0, __0, @@ -47977,24 +48115,24 @@ fn __action876< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action877< +fn __action881< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action696( + __action698( mode, __temp0, __0, @@ -48006,22 +48144,22 @@ fn __action877< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action878< +fn __action882< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, ast::Parameter, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action697( + __action699( mode, __temp0, __0, @@ -48031,21 +48169,21 @@ fn __action878< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action879< +fn __action883< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action698( + __action700( mode, __temp0, __0, @@ -48054,23 +48192,23 @@ fn __action879< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action880< +fn __action884< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action699( + __action701( mode, __temp0, __0, @@ -48081,22 +48219,22 @@ fn __action880< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action881< +fn __action885< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action700( + __action702( mode, __temp0, __0, @@ -48106,24 +48244,24 @@ fn __action881< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action882< +fn __action886< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), + __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action689( + __action691( mode, __temp0, __0, @@ -48135,25 +48273,25 @@ fn __action882< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action883< +fn __action887< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, core::option::Option, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action690( + __action692( mode, __temp0, __0, @@ -48166,22 +48304,22 @@ fn __action883< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action884< +fn __action888< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, core::option::Option, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action691( + __action693( mode, __temp0, __0, @@ -48191,23 +48329,23 @@ fn __action884< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action885< +fn __action889< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, core::option::Option, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action692( + __action694( mode, __temp0, __0, @@ -48218,24 +48356,24 @@ fn __action885< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action886< +fn __action890< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), + __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action164( + __action167( mode, __temp0, __0, @@ -48247,7 +48385,7 @@ fn __action886< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action887< +fn __action891< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48256,13 +48394,13 @@ fn __action887< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action23( + __action24( mode, __temp0, __0, @@ -48272,7 +48410,7 @@ fn __action887< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action888< +fn __action892< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -48282,13 +48420,13 @@ fn __action888< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action88( + __action90( mode, __temp0, __0, @@ -48299,7 +48437,7 @@ fn __action888< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action889< +fn __action893< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -48309,13 +48447,13 @@ fn __action889< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action634( + __action639( mode, __temp0, __0, @@ -48326,7 +48464,7 @@ fn __action889< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action890< +fn __action894< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -48335,13 +48473,13 @@ fn __action890< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action635( + __action640( mode, __temp0, __0, @@ -48351,7 +48489,7 @@ fn __action890< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action891< +fn __action895< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48362,13 +48500,13 @@ fn __action891< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action505( + __action508( mode, __temp0, __0, @@ -48380,7 +48518,7 @@ fn __action891< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action892< +fn __action896< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48391,13 +48529,13 @@ fn __action892< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action554( + __action559( mode, __temp0, __0, @@ -48409,7 +48547,7 @@ fn __action892< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action893< +fn __action897< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48418,13 +48556,13 @@ fn __action893< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action57( + __action58( mode, __temp0, __0, @@ -48434,7 +48572,7 @@ fn __action893< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action894< +fn __action898< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48445,13 +48583,13 @@ fn __action894< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action58( + __action59( mode, __temp0, __0, @@ -48463,7 +48601,7 @@ fn __action894< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action895< +fn __action899< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48474,13 +48612,13 @@ fn __action895< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action103( + __action105( mode, __temp0, __0, @@ -48492,7 +48630,7 @@ fn __action895< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action896< +fn __action900< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48502,13 +48640,13 @@ fn __action896< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action104( + __action106( mode, __temp0, __0, @@ -48519,7 +48657,7 @@ fn __action896< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action897< +fn __action901< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48531,13 +48669,13 @@ fn __action897< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action105( + __action107( mode, __temp0, __0, @@ -48550,7 +48688,7 @@ fn __action897< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action898< +fn __action902< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48563,13 +48701,13 @@ fn __action898< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action636( + __action641( mode, __temp0, __0, @@ -48583,7 +48721,7 @@ fn __action898< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action899< +fn __action903< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48595,13 +48733,13 @@ fn __action899< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action637( + __action642( mode, __temp0, __0, @@ -48614,7 +48752,7 @@ fn __action899< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action900< +fn __action904< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48625,13 +48763,13 @@ fn __action900< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action107( + __action109( mode, __temp0, __0, @@ -48643,7 +48781,7 @@ fn __action900< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action901< +fn __action905< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48654,13 +48792,13 @@ fn __action901< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action484( + __action483( mode, __temp0, __0, @@ -48672,7 +48810,7 @@ fn __action901< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action902< +fn __action906< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48683,13 +48821,13 @@ fn __action902< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action511( + __action520( mode, __temp0, __0, @@ -48701,7 +48839,7 @@ fn __action902< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action903< +fn __action907< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48715,13 +48853,13 @@ fn __action903< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action660( + __action665( mode, __temp0, __0, @@ -48736,7 +48874,7 @@ fn __action903< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action904< +fn __action908< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48749,13 +48887,13 @@ fn __action904< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action661( + __action666( mode, __temp0, __0, @@ -48769,7 +48907,7 @@ fn __action904< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action905< +fn __action909< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48778,13 +48916,13 @@ fn __action905< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action209( + __action213( mode, __temp0, __0, @@ -48794,7 +48932,7 @@ fn __action905< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action906< +fn __action910< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48804,13 +48942,13 @@ fn __action906< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action221( + __action225( mode, __temp0, __0, @@ -48821,7 +48959,7 @@ fn __action906< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action907< +fn __action911< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -48831,13 +48969,13 @@ fn __action907< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action108( + __action110( mode, __temp0, __0, @@ -48848,23 +48986,23 @@ fn __action907< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action908< +fn __action912< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action168( + __action171( mode, __temp0, __0, @@ -48875,22 +49013,22 @@ fn __action908< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action909< +fn __action913< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action166( + __action169( mode, __temp0, __0, @@ -48900,7 +49038,7 @@ fn __action909< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action910< +fn __action914< >( mode: Mode, __0: (TextSize, core::option::Option, TextSize), @@ -48912,13 +49050,13 @@ fn __action910< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action208( + __action212( mode, __temp0, __0, @@ -48931,7 +49069,7 @@ fn __action910< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action911< +fn __action915< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48940,13 +49078,13 @@ fn __action911< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action204( + __action208( mode, __temp0, __0, @@ -48956,7 +49094,7 @@ fn __action911< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action912< +fn __action916< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -48966,13 +49104,13 @@ fn __action912< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action205( + __action209( mode, __temp0, __0, @@ -48983,7 +49121,7 @@ fn __action912< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action913< +fn __action917< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -48993,13 +49131,13 @@ fn __action913< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action640( + __action645( mode, __temp0, __0, @@ -49010,7 +49148,7 @@ fn __action913< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action914< +fn __action918< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -49019,13 +49157,13 @@ fn __action914< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action641( + __action646( mode, __temp0, __0, @@ -49035,7 +49173,7 @@ fn __action914< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action915< +fn __action919< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49046,13 +49184,13 @@ fn __action915< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action497( + __action500( mode, __temp0, __0, @@ -49064,7 +49202,7 @@ fn __action915< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action916< +fn __action920< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49075,13 +49213,13 @@ fn __action916< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action538( + __action553( mode, __temp0, __0, @@ -49093,7 +49231,7 @@ fn __action916< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action917< +fn __action921< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49106,13 +49244,13 @@ fn __action917< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action376( + __action381( mode, __temp0, __0, @@ -49126,7 +49264,7 @@ fn __action917< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action918< +fn __action922< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49139,13 +49277,13 @@ fn __action918< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action406( + __action413( mode, __temp0, __0, @@ -49159,7 +49297,7 @@ fn __action918< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action919< +fn __action923< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49169,7 +49307,7 @@ fn __action919< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -49186,7 +49324,7 @@ fn __action919< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action920< +fn __action924< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49197,7 +49335,7 @@ fn __action920< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -49215,7 +49353,7 @@ fn __action920< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action921< +fn __action925< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49229,13 +49367,13 @@ fn __action921< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action148( + __action150( mode, __temp0, __0, @@ -49250,7 +49388,7 @@ fn __action921< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action922< +fn __action926< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49264,13 +49402,13 @@ fn __action922< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action149( + __action151( mode, __temp0, __0, @@ -49285,7 +49423,7 @@ fn __action922< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action923< +fn __action927< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49296,13 +49434,13 @@ fn __action923< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action150( + __action152( mode, __temp0, __0, @@ -49314,7 +49452,7 @@ fn __action923< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action924< +fn __action928< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -49323,13 +49461,13 @@ fn __action924< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action162( + __action165( mode, __temp0, __0, @@ -49339,12 +49477,12 @@ fn __action924< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action925< +fn __action929< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Expr, TextSize), - __2: (TextSize, core::option::Option>, TextSize), + __2: (TextSize, core::option::Option, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Expr, TextSize), __5: (TextSize, TextSize, TextSize), @@ -49352,13 +49490,13 @@ fn __action925< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action163( + __action166( mode, __temp0, __0, @@ -49372,7 +49510,7 @@ fn __action925< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action926< +fn __action930< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -49382,13 +49520,13 @@ fn __action926< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action172( + __action175( mode, __temp0, __0, @@ -49399,7 +49537,7 @@ fn __action926< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action927< +fn __action931< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49409,13 +49547,13 @@ fn __action927< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action173( + __action176( mode, __temp0, __0, @@ -49426,7 +49564,7 @@ fn __action927< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action928< +fn __action932< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49436,13 +49574,13 @@ fn __action928< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action174( + __action177( mode, __temp0, __0, @@ -49453,7 +49591,7 @@ fn __action928< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action929< +fn __action933< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49461,17 +49599,17 @@ fn __action929< __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action642( + __action647( mode, __temp0, __0, @@ -49484,24 +49622,24 @@ fn __action929< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action930< +fn __action934< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, Vec, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action643( + __action648( mode, __temp0, __0, @@ -49513,23 +49651,23 @@ fn __action930< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action931< +fn __action935< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action167( + __action170( mode, __temp0, __0, @@ -49540,22 +49678,22 @@ fn __action931< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action932< +fn __action936< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action165( + __action168( mode, __temp0, __0, @@ -49565,7 +49703,7 @@ fn __action932< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action933< +fn __action937< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49574,13 +49712,13 @@ fn __action933< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action123( + __action125( mode, __temp0, __0, @@ -49590,7 +49728,7 @@ fn __action933< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action934< +fn __action938< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49602,13 +49740,13 @@ fn __action934< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action146( + __action148( mode, __temp0, __0, @@ -49621,7 +49759,7 @@ fn __action934< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action935< +fn __action939< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49630,34 +49768,7 @@ fn __action935< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action298( - mode, - __temp0, - __0, - __1, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action936< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Expr, TextSize), - __3: (TextSize, TextSize, TextSize), -) -> ast::WithItem -{ - let __start0 = __0.0; - let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, @@ -49668,43 +49779,12 @@ fn __action936< __temp0, __0, __1, - __2, - __3, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action937< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Expr, TextSize), - __3: (TextSize, TextSize, TextSize), -) -> ast::WithItem -{ - let __start0 = __0.0; - let __end0 = __0.0; - let __temp0 = __action390( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action300( - mode, - __temp0, - __0, - __1, - __2, - __3, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action938< +fn __action940< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49713,13 +49793,13 @@ fn __action938< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action293( + __action294( mode, __temp0, __0, @@ -49729,7 +49809,7 @@ fn __action938< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action939< +fn __action941< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49740,13 +49820,13 @@ fn __action939< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action294( + __action163( mode, __temp0, __0, @@ -49758,7 +49838,7 @@ fn __action939< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action940< +fn __action942< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -49767,13 +49847,13 @@ fn __action940< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action160( + __action162( mode, __temp0, __0, @@ -49783,7 +49863,7 @@ fn __action940< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action941< +fn __action943< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49795,13 +49875,13 @@ fn __action941< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action662( + __action667( mode, __temp0, __0, @@ -49814,7 +49894,7 @@ fn __action941< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action942< +fn __action944< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49825,13 +49905,13 @@ fn __action942< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action663( + __action668( mode, __temp0, __0, @@ -49843,7 +49923,7 @@ fn __action942< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action943< +fn __action945< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49854,13 +49934,13 @@ fn __action943< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action427( + __action405( mode, __temp0, __0, @@ -49872,7 +49952,7 @@ fn __action943< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action944< +fn __action946< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -49883,13 +49963,13 @@ fn __action944< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action503( + __action510( mode, __temp0, __0, @@ -49901,7 +49981,7 @@ fn __action944< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action945< +fn __action947< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49911,13 +49991,13 @@ fn __action945< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action176( + __action179( mode, __temp0, __0, @@ -49928,7 +50008,7 @@ fn __action945< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action946< +fn __action948< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -49939,13 +50019,13 @@ fn __action946< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action390( + let __temp0 = __action395( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action177( + __action180( mode, __temp0, __0, @@ -49957,19 +50037,19 @@ fn __action946< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action947< +fn __action949< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), + __2: (TextSize, ast::Parameter, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action874( + let __temp0 = __action878( mode, __1, __2, @@ -49977,7 +50057,7 @@ fn __action947< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -49986,25 +50066,25 @@ fn __action947< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action948< +fn __action950< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action875( + let __temp0 = __action879( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50013,20 +50093,20 @@ fn __action948< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action949< +fn __action951< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action876( + let __temp0 = __action880( mode, __1, __2, @@ -50035,7 +50115,7 @@ fn __action949< __5, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50044,19 +50124,19 @@ fn __action949< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action950< +fn __action952< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action877( + let __temp0 = __action881( mode, __1, __2, @@ -50064,7 +50144,7 @@ fn __action950< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50073,23 +50153,23 @@ fn __action950< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action951< +fn __action953< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action878( + let __temp0 = __action882( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50098,21 +50178,21 @@ fn __action951< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action952< +fn __action954< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action879( + let __temp0 = __action883( mode, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50121,25 +50201,25 @@ fn __action952< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action953< +fn __action955< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action880( + let __temp0 = __action884( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50148,23 +50228,23 @@ fn __action953< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action954< +fn __action956< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action881( + let __temp0 = __action885( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action415( + Ok(__action422( mode, __0, __temp0, @@ -50173,20 +50253,20 @@ fn __action954< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action955< +fn __action957< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action874( + let __temp0 = __action878( mode, __0, __1, @@ -50194,7 +50274,7 @@ fn __action955< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __4, @@ -50204,26 +50284,26 @@ fn __action955< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action956< +fn __action958< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action875( + let __temp0 = __action879( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __3, @@ -50233,21 +50313,21 @@ fn __action956< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action957< +fn __action959< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action876( + let __temp0 = __action880( mode, __0, __1, @@ -50256,7 +50336,7 @@ fn __action957< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __5, @@ -50266,20 +50346,20 @@ fn __action957< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action958< +fn __action960< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action877( + let __temp0 = __action881( mode, __0, __1, @@ -50287,7 +50367,7 @@ fn __action958< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __4, @@ -50297,24 +50377,24 @@ fn __action958< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action959< +fn __action961< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action878( + let __temp0 = __action882( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __2, @@ -50324,22 +50404,22 @@ fn __action959< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action960< +fn __action962< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action879( + let __temp0 = __action883( mode, __0, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __1, @@ -50349,26 +50429,26 @@ fn __action960< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action961< +fn __action963< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action880( + let __temp0 = __action884( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __3, @@ -50378,24 +50458,24 @@ fn __action961< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action962< +fn __action964< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action881( + let __temp0 = __action885( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action862( + Ok(__action866( mode, __temp0, __2, @@ -50405,19 +50485,19 @@ fn __action962< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action963< +fn __action965< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action874( + let __temp0 = __action878( mode, __0, __1, @@ -50425,7 +50505,7 @@ fn __action963< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __4, @@ -50434,25 +50514,25 @@ fn __action963< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action964< +fn __action966< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action875( + let __temp0 = __action879( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __3, @@ -50461,20 +50541,20 @@ fn __action964< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action965< +fn __action967< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action876( + let __temp0 = __action880( mode, __0, __1, @@ -50483,7 +50563,7 @@ fn __action965< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __5, @@ -50492,19 +50572,19 @@ fn __action965< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action966< +fn __action968< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action877( + let __temp0 = __action881( mode, __0, __1, @@ -50512,7 +50592,7 @@ fn __action966< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __4, @@ -50521,23 +50601,23 @@ fn __action966< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action967< +fn __action969< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action878( + let __temp0 = __action882( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __2, @@ -50546,21 +50626,21 @@ fn __action967< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action968< +fn __action970< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action879( + let __temp0 = __action883( mode, __0, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __1, @@ -50569,25 +50649,25 @@ fn __action968< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action969< +fn __action971< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action880( + let __temp0 = __action884( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __3, @@ -50596,23 +50676,23 @@ fn __action969< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action970< +fn __action972< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action881( + let __temp0 = __action885( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action863( + Ok(__action867( mode, __temp0, __2, @@ -50621,19 +50701,19 @@ fn __action970< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action971< +fn __action973< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), + __2: (TextSize, ast::Parameter, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action947( + let __temp0 = __action949( mode, __0, __1, @@ -50642,7 +50722,7 @@ fn __action971< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50650,18 +50730,18 @@ fn __action971< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action972< +fn __action974< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action948( + let __temp0 = __action950( mode, __0, __1, @@ -50669,7 +50749,7 @@ fn __action972< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50677,20 +50757,20 @@ fn __action972< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action973< +fn __action975< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __5.2; - let __temp0 = __action949( + let __temp0 = __action951( mode, __0, __1, @@ -50700,7 +50780,7 @@ fn __action973< __5, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50708,19 +50788,19 @@ fn __action973< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action974< +fn __action976< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action950( + let __temp0 = __action952( mode, __0, __1, @@ -50729,7 +50809,7 @@ fn __action974< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50737,24 +50817,24 @@ fn __action974< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action975< +fn __action977< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action951( + let __temp0 = __action953( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50762,22 +50842,22 @@ fn __action975< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action976< +fn __action978< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action952( + let __temp0 = __action954( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50785,18 +50865,18 @@ fn __action976< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action977< +fn __action979< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action953( + let __temp0 = __action955( mode, __0, __1, @@ -50804,7 +50884,7 @@ fn __action977< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50812,24 +50892,24 @@ fn __action977< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action978< +fn __action980< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action954( + let __temp0 = __action956( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action413( + Ok(__action420( mode, __temp0, )) @@ -50837,22 +50917,22 @@ fn __action978< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action979< +fn __action981< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action971( + let __temp0 = __action973( mode, __1, __2, @@ -50861,7 +50941,7 @@ fn __action979< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -50872,21 +50952,21 @@ fn __action979< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action980< +fn __action982< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action972( + let __temp0 = __action974( mode, __1, __2, @@ -50894,7 +50974,7 @@ fn __action980< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -50905,23 +50985,23 @@ fn __action980< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action981< +fn __action983< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), __8: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __6.2; - let __temp0 = __action973( + let __temp0 = __action975( mode, __1, __2, @@ -50931,7 +51011,7 @@ fn __action981< __6, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -50942,22 +51022,22 @@ fn __action981< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action982< +fn __action984< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action974( + let __temp0 = __action976( mode, __1, __2, @@ -50966,7 +51046,7 @@ fn __action982< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -50977,27 +51057,27 @@ fn __action982< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action983< +fn __action985< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action975( + let __temp0 = __action977( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -51008,25 +51088,25 @@ fn __action983< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action984< +fn __action986< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action976( + let __temp0 = __action978( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -51037,21 +51117,21 @@ fn __action984< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action985< +fn __action987< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action977( + let __temp0 = __action979( mode, __1, __2, @@ -51059,7 +51139,7 @@ fn __action985< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -51070,27 +51150,27 @@ fn __action985< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action986< +fn __action988< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action978( + let __temp0 = __action980( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -51101,23 +51181,23 @@ fn __action986< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action987< +fn __action989< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action414( + let __temp0 = __action421( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action858( + __action862( mode, __0, __temp0, @@ -51128,21 +51208,21 @@ fn __action987< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action988< +fn __action990< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action971( + let __temp0 = __action973( mode, __1, __2, @@ -51151,7 +51231,7 @@ fn __action988< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51161,20 +51241,20 @@ fn __action988< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action989< +fn __action991< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action972( + let __temp0 = __action974( mode, __1, __2, @@ -51182,7 +51262,7 @@ fn __action989< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51192,22 +51272,22 @@ fn __action989< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action990< +fn __action992< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __6.2; - let __temp0 = __action973( + let __temp0 = __action975( mode, __1, __2, @@ -51217,7 +51297,7 @@ fn __action990< __6, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51227,21 +51307,21 @@ fn __action990< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action991< +fn __action993< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action974( + let __temp0 = __action976( mode, __1, __2, @@ -51250,7 +51330,7 @@ fn __action991< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51260,26 +51340,26 @@ fn __action991< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action992< +fn __action994< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action975( + let __temp0 = __action977( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51289,24 +51369,24 @@ fn __action992< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action993< +fn __action995< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action976( + let __temp0 = __action978( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51316,20 +51396,20 @@ fn __action993< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action994< +fn __action996< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action977( + let __temp0 = __action979( mode, __1, __2, @@ -51337,7 +51417,7 @@ fn __action994< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51347,26 +51427,26 @@ fn __action994< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action995< +fn __action997< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action978( + let __temp0 = __action980( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51376,22 +51456,22 @@ fn __action995< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action996< +fn __action998< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action414( + let __temp0 = __action421( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action859( + __action863( mode, __0, __temp0, @@ -51401,21 +51481,21 @@ fn __action996< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action997< +fn __action999< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Option> + __1: (TextSize, ast::Parameter, TextSize), +) -> Option> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action461( + let __temp0 = __action464( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action420( + __action427( mode, __0, __temp0, @@ -51424,21 +51504,21 @@ fn __action997< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action998< +fn __action1000< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Option> +) -> Option> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action462( + let __temp0 = __action465( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action420( + __action427( mode, __0, __temp0, @@ -51447,23 +51527,23 @@ fn __action998< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action999< +fn __action1001< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action461( + let __temp0 = __action464( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action882( + __action886( mode, __0, __temp0, @@ -51474,23 +51554,23 @@ fn __action999< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1000< +fn __action1002< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action462( + let __temp0 = __action465( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action882( + __action886( mode, __0, __temp0, @@ -51501,24 +51581,24 @@ fn __action1000< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1001< +fn __action1003< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action461( + let __temp0 = __action464( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action883( + __action887( mode, __0, __temp0, @@ -51530,24 +51610,24 @@ fn __action1001< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1002< +fn __action1004< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action462( + let __temp0 = __action465( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action883( + __action887( mode, __0, __temp0, @@ -51559,21 +51639,21 @@ fn __action1002< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1003< +fn __action1005< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, ast::Parameter, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action461( + let __temp0 = __action464( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action884( + __action888( mode, __0, __temp0, @@ -51582,21 +51662,21 @@ fn __action1003< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1004< +fn __action1006< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action462( + let __temp0 = __action465( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action884( + __action888( mode, __0, __temp0, @@ -51605,22 +51685,22 @@ fn __action1004< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1005< +fn __action1007< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action461( + let __temp0 = __action464( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action885( + __action889( mode, __0, __temp0, @@ -51630,22 +51710,22 @@ fn __action1005< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1006< +fn __action1008< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __1: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action462( + let __temp0 = __action465( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action885( + __action889( mode, __0, __temp0, @@ -51655,19 +51735,19 @@ fn __action1006< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1007< +fn __action1009< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), + __2: (TextSize, ast::Parameter, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action999( + let __temp0 = __action1001( mode, __1, __2, @@ -51675,7 +51755,7 @@ fn __action1007< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51684,25 +51764,25 @@ fn __action1007< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1008< +fn __action1010< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1000( + let __temp0 = __action1002( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51711,20 +51791,20 @@ fn __action1008< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1009< +fn __action1011< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action1001( + let __temp0 = __action1003( mode, __1, __2, @@ -51733,7 +51813,7 @@ fn __action1009< __5, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51742,19 +51822,19 @@ fn __action1009< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1010< +fn __action1012< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action1002( + let __temp0 = __action1004( mode, __1, __2, @@ -51762,7 +51842,7 @@ fn __action1010< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51771,23 +51851,23 @@ fn __action1010< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1011< +fn __action1013< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1003( + let __temp0 = __action1005( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51796,21 +51876,21 @@ fn __action1011< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1012< +fn __action1014< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1004( + let __temp0 = __action1006( mode, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51819,25 +51899,25 @@ fn __action1012< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1013< +fn __action1015< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1005( + let __temp0 = __action1007( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51846,23 +51926,23 @@ fn __action1013< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1014< +fn __action1016< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result<(Option>, Vec, Option>),__lalrpop_util::ParseError> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1006( + let __temp0 = __action1008( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action423( + Ok(__action430( mode, __0, __temp0, @@ -51871,20 +51951,20 @@ fn __action1014< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1015< +fn __action1017< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action999( + let __temp0 = __action1001( mode, __0, __1, @@ -51892,7 +51972,7 @@ fn __action1015< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __4, @@ -51902,26 +51982,26 @@ fn __action1015< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1016< +fn __action1018< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1000( + let __temp0 = __action1002( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __3, @@ -51931,21 +52011,21 @@ fn __action1016< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1017< +fn __action1019< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action1001( + let __temp0 = __action1003( mode, __0, __1, @@ -51954,7 +52034,7 @@ fn __action1017< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __5, @@ -51964,20 +52044,20 @@ fn __action1017< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1018< +fn __action1020< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action1002( + let __temp0 = __action1004( mode, __0, __1, @@ -51985,7 +52065,7 @@ fn __action1018< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __4, @@ -51995,24 +52075,24 @@ fn __action1018< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1019< +fn __action1021< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1003( + let __temp0 = __action1005( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __2, @@ -52022,22 +52102,22 @@ fn __action1019< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1020< +fn __action1022< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1004( + let __temp0 = __action1006( mode, __0, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __1, @@ -52047,26 +52127,26 @@ fn __action1020< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1021< +fn __action1023< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1005( + let __temp0 = __action1007( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __3, @@ -52076,24 +52156,24 @@ fn __action1021< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1022< +fn __action1024< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1006( + let __temp0 = __action1008( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action870( + Ok(__action874( mode, __temp0, __2, @@ -52103,19 +52183,19 @@ fn __action1022< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1023< +fn __action1025< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action999( + let __temp0 = __action1001( mode, __0, __1, @@ -52123,7 +52203,7 @@ fn __action1023< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __4, @@ -52132,25 +52212,25 @@ fn __action1023< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1024< +fn __action1026< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1000( + let __temp0 = __action1002( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __3, @@ -52159,20 +52239,20 @@ fn __action1024< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1025< +fn __action1027< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action1001( + let __temp0 = __action1003( mode, __0, __1, @@ -52181,7 +52261,7 @@ fn __action1025< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __5, @@ -52190,19 +52270,19 @@ fn __action1025< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1026< +fn __action1028< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action1002( + let __temp0 = __action1004( mode, __0, __1, @@ -52210,7 +52290,7 @@ fn __action1026< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __4, @@ -52219,23 +52299,23 @@ fn __action1026< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1027< +fn __action1029< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1003( + let __temp0 = __action1005( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __2, @@ -52244,21 +52324,21 @@ fn __action1027< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1028< +fn __action1030< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1004( + let __temp0 = __action1006( mode, __0, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __1, @@ -52267,25 +52347,25 @@ fn __action1028< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1029< +fn __action1031< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1005( + let __temp0 = __action1007( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __3, @@ -52294,23 +52374,23 @@ fn __action1029< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1030< +fn __action1032< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1006( + let __temp0 = __action1008( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action871( + Ok(__action875( mode, __temp0, __2, @@ -52319,19 +52399,19 @@ fn __action1030< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1031< +fn __action1033< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), + __2: (TextSize, ast::Parameter, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action1007( + let __temp0 = __action1009( mode, __0, __1, @@ -52340,7 +52420,7 @@ fn __action1031< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52348,18 +52428,18 @@ fn __action1031< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1032< +fn __action1034< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __3: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action1008( + let __temp0 = __action1010( mode, __0, __1, @@ -52367,7 +52447,7 @@ fn __action1032< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52375,20 +52455,20 @@ fn __action1032< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1033< +fn __action1035< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __5: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __5.2; - let __temp0 = __action1009( + let __temp0 = __action1011( mode, __0, __1, @@ -52398,7 +52478,7 @@ fn __action1033< __5, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52406,19 +52486,19 @@ fn __action1033< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1034< +fn __action1036< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __4: (TextSize, Option>, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __4.2; - let __temp0 = __action1010( + let __temp0 = __action1012( mode, __0, __1, @@ -52427,7 +52507,7 @@ fn __action1034< __4, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52435,24 +52515,24 @@ fn __action1034< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1035< +fn __action1037< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1011( + let __temp0 = __action1013( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52460,22 +52540,22 @@ fn __action1035< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1036< +fn __action1038< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1012( + let __temp0 = __action1014( mode, __0, __1, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52483,18 +52563,18 @@ fn __action1036< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1037< +fn __action1039< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Arg, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, ast::Parameter, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action1013( + let __temp0 = __action1015( mode, __0, __1, @@ -52502,7 +52582,7 @@ fn __action1037< __3, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52510,24 +52590,24 @@ fn __action1037< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1038< +fn __action1040< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result>, Vec, Option>)>,__lalrpop_util::ParseError> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1014( + let __temp0 = __action1016( mode, __0, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - Ok(__action421( + Ok(__action428( mode, __temp0, )) @@ -52535,22 +52615,22 @@ fn __action1038< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1039< +fn __action1041< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action1031( + let __temp0 = __action1033( mode, __1, __2, @@ -52559,7 +52639,7 @@ fn __action1039< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52570,21 +52650,21 @@ fn __action1039< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1040< +fn __action1042< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action1032( + let __temp0 = __action1034( mode, __1, __2, @@ -52592,7 +52672,7 @@ fn __action1040< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52603,23 +52683,23 @@ fn __action1040< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1041< +fn __action1043< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), __8: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __6.2; - let __temp0 = __action1033( + let __temp0 = __action1035( mode, __1, __2, @@ -52629,7 +52709,7 @@ fn __action1041< __6, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52640,22 +52720,22 @@ fn __action1041< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1042< +fn __action1044< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action1034( + let __temp0 = __action1036( mode, __1, __2, @@ -52664,7 +52744,7 @@ fn __action1042< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52675,27 +52755,27 @@ fn __action1042< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1043< +fn __action1045< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1035( + let __temp0 = __action1037( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52706,25 +52786,25 @@ fn __action1043< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1044< +fn __action1046< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1036( + let __temp0 = __action1038( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52735,21 +52815,21 @@ fn __action1044< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1045< +fn __action1047< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action1037( + let __temp0 = __action1039( mode, __1, __2, @@ -52757,7 +52837,7 @@ fn __action1045< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52768,27 +52848,27 @@ fn __action1045< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1046< +fn __action1048< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1038( + let __temp0 = __action1040( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52799,23 +52879,23 @@ fn __action1046< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1047< +fn __action1049< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action422( + let __temp0 = __action429( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action866( + __action870( mode, __0, __temp0, @@ -52826,21 +52906,21 @@ fn __action1047< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1048< +fn __action1050< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action1031( + let __temp0 = __action1033( mode, __1, __2, @@ -52849,7 +52929,7 @@ fn __action1048< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -52859,20 +52939,20 @@ fn __action1048< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1049< +fn __action1051< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action1032( + let __temp0 = __action1034( mode, __1, __2, @@ -52880,7 +52960,7 @@ fn __action1049< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -52890,22 +52970,22 @@ fn __action1049< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1050< +fn __action1052< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __6.2; - let __temp0 = __action1033( + let __temp0 = __action1035( mode, __1, __2, @@ -52915,7 +52995,7 @@ fn __action1050< __6, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -52925,21 +53005,21 @@ fn __action1050< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1051< +fn __action1053< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __5.2; - let __temp0 = __action1034( + let __temp0 = __action1036( mode, __1, __2, @@ -52948,7 +53028,7 @@ fn __action1051< __5, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -52958,26 +53038,26 @@ fn __action1051< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1052< +fn __action1054< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1035( + let __temp0 = __action1037( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -52987,24 +53067,24 @@ fn __action1052< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1053< +fn __action1055< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1036( + let __temp0 = __action1038( mode, __1, __2, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -53014,20 +53094,20 @@ fn __action1053< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1054< +fn __action1056< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action1037( + let __temp0 = __action1039( mode, __1, __2, @@ -53035,7 +53115,7 @@ fn __action1054< __4, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -53045,26 +53125,26 @@ fn __action1054< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1055< +fn __action1057< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __3.2; - let __temp0 = __action1038( + let __temp0 = __action1040( mode, __1, __2, __3, )?; let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -53074,22 +53154,22 @@ fn __action1055< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1056< +fn __action1058< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, TextSize, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action422( + let __temp0 = __action429( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action867( + __action871( mode, __0, __temp0, @@ -53099,7 +53179,7 @@ fn __action1056< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1057< +fn __action1059< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53108,13 +53188,13 @@ fn __action1057< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action351( + let __temp0 = __action356( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action349( + __action354( mode, __temp0, ) @@ -53122,7 +53202,7 @@ fn __action1057< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1058< +fn __action1060< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53134,13 +53214,13 @@ fn __action1058< { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action1057( + let __temp0 = __action1059( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action712( + __action715( mode, __0, __1, @@ -53151,7 +53231,7 @@ fn __action1058< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1059< +fn __action1061< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53161,13 +53241,13 @@ fn __action1059< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action350( + let __temp0 = __action355( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action712( + __action715( mode, __0, __1, @@ -53178,7 +53258,7 @@ fn __action1059< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1060< +fn __action1062< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53187,13 +53267,13 @@ fn __action1060< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action544( + let __temp0 = __action547( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action550( + __action557( mode, __temp0, ) @@ -53201,7 +53281,7 @@ fn __action1060< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1061< +fn __action1063< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -53211,13 +53291,13 @@ fn __action1061< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action544( + let __temp0 = __action547( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action551( + __action558( mode, __0, __temp0, @@ -53226,7 +53306,7 @@ fn __action1061< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1062< +fn __action1064< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53239,13 +53319,13 @@ fn __action1062< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action542( + let __temp0 = __action545( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action720( + __action723( mode, __0, __1, @@ -53259,7 +53339,7 @@ fn __action1062< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1063< +fn __action1065< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53273,12 +53353,12 @@ fn __action1063< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action543( + let __temp0 = __action546( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action720( + __action723( mode, __0, __1, @@ -53292,7 +53372,7 @@ fn __action1063< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1064< +fn __action1066< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53304,13 +53384,13 @@ fn __action1064< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action542( + let __temp0 = __action545( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action721( + __action724( mode, __0, __1, @@ -53323,7 +53403,7 @@ fn __action1064< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1065< +fn __action1067< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53336,12 +53416,12 @@ fn __action1065< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action543( + let __temp0 = __action546( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action721( + __action724( mode, __0, __1, @@ -53354,7 +53434,7 @@ fn __action1065< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1066< +fn __action1068< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53367,13 +53447,13 @@ fn __action1066< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action542( + let __temp0 = __action545( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action738( + __action741( mode, __0, __1, @@ -53387,7 +53467,7 @@ fn __action1066< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1067< +fn __action1069< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53401,12 +53481,12 @@ fn __action1067< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action543( + let __temp0 = __action546( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action738( + __action741( mode, __0, __1, @@ -53420,7 +53500,7 @@ fn __action1067< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1068< +fn __action1070< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53432,13 +53512,13 @@ fn __action1068< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action542( + let __temp0 = __action545( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action739( + __action742( mode, __0, __1, @@ -53451,7 +53531,7 @@ fn __action1068< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1069< +fn __action1071< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53464,12 +53544,12 @@ fn __action1069< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action543( + let __temp0 = __action546( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action739( + __action742( mode, __0, __1, @@ -53482,7 +53562,7 @@ fn __action1069< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1070< +fn __action1072< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53491,13 +53571,13 @@ fn __action1070< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action297( + let __temp0 = __action298( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action291( + __action292( mode, __temp0, ) @@ -53505,7 +53585,7 @@ fn __action1070< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1071< +fn __action1073< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -53515,13 +53595,13 @@ fn __action1071< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action297( + let __temp0 = __action298( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action292( + __action293( mode, __0, __temp0, @@ -53530,7 +53610,7 @@ fn __action1071< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1072< +fn __action1074< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53542,13 +53622,13 @@ fn __action1072< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action295( + let __temp0 = __action296( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action646( + __action651( mode, __0, __1, @@ -53561,7 +53641,7 @@ fn __action1072< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1073< +fn __action1075< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53574,12 +53654,12 @@ fn __action1073< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action296( + let __temp0 = __action297( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action646( + __action651( mode, __0, __1, @@ -53592,7 +53672,7 @@ fn __action1073< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1074< +fn __action1076< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53603,13 +53683,13 @@ fn __action1074< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action295( + let __temp0 = __action296( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action647( + __action652( mode, __0, __1, @@ -53621,7 +53701,7 @@ fn __action1074< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1075< +fn __action1077< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53633,12 +53713,12 @@ fn __action1075< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action296( + let __temp0 = __action297( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action647( + __action652( mode, __0, __1, @@ -53650,7 +53730,7 @@ fn __action1075< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1076< +fn __action1078< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53659,13 +53739,13 @@ fn __action1076< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action284( + let __temp0 = __action285( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action282( + __action283( mode, __temp0, ) @@ -53673,15 +53753,15 @@ fn __action1076< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1077< +fn __action1079< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Expr, TextSize), __8: (TextSize, token::Tok, TextSize), @@ -53690,13 +53770,13 @@ fn __action1077< { let __start0 = __6.0; let __end0 = __7.2; - let __temp0 = __action1076( + let __temp0 = __action1078( mode, __6, __7, ); let __temp0 = (__start0, __temp0, __end0); - __action802( + __action804( mode, __0, __1, @@ -53712,28 +53792,28 @@ fn __action1077< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1078< +fn __action1080< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __5.2; let __end0 = __6.0; - let __temp0 = __action283( + let __temp0 = __action284( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action802( + __action804( mode, __0, __1, @@ -53749,14 +53829,14 @@ fn __action1078< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1079< +fn __action1081< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -53765,13 +53845,13 @@ fn __action1079< { let __start0 = __5.0; let __end0 = __6.2; - let __temp0 = __action1076( + let __temp0 = __action1078( mode, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action803( + __action805( mode, __0, __1, @@ -53786,27 +53866,27 @@ fn __action1079< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1080< +fn __action1082< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __4.2; let __end0 = __5.0; - let __temp0 = __action283( + let __temp0 = __action284( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action803( + __action805( mode, __0, __1, @@ -53821,7 +53901,7 @@ fn __action1080< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1081< +fn __action1083< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53830,13 +53910,13 @@ fn __action1081< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action356( + let __temp0 = __action361( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action354( + __action359( mode, __temp0, ) @@ -53844,7 +53924,7 @@ fn __action1081< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1082< +fn __action1084< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(token::Tok, ast::Identifier)>, TextSize), @@ -53854,13 +53934,13 @@ fn __action1082< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action356( + let __temp0 = __action361( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action355( + __action360( mode, __0, __temp0, @@ -53869,7 +53949,7 @@ fn __action1082< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1083< +fn __action1085< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -53878,13 +53958,13 @@ fn __action1083< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action274( + let __temp0 = __action275( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action272( + __action273( mode, __temp0, ) @@ -53892,24 +53972,24 @@ fn __action1083< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1084< +fn __action1086< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1083( + let __temp0 = __action1085( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action784( + __action786( mode, __0, __temp0, @@ -53919,22 +53999,22 @@ fn __action1084< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1085< +fn __action1087< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action273( + let __temp0 = __action274( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action784( + __action786( mode, __0, __temp0, @@ -53944,7 +54024,7 @@ fn __action1085< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1086< +fn __action1088< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -53955,13 +54035,13 @@ fn __action1086< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1083( + let __temp0 = __action1085( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action926( + __action930( mode, __0, __temp0, @@ -53971,7 +54051,7 @@ fn __action1086< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1087< +fn __action1089< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -53980,13 +54060,13 @@ fn __action1087< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action273( + let __temp0 = __action274( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action926( + __action930( mode, __0, __temp0, @@ -53996,24 +54076,24 @@ fn __action1087< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1088< +fn __action1090< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1083( + let __temp0 = __action1085( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action931( + __action935( mode, __0, __temp0, @@ -54023,22 +54103,22 @@ fn __action1088< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1089< +fn __action1091< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action273( + let __temp0 = __action274( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action931( + __action935( mode, __0, __temp0, @@ -54048,7 +54128,7 @@ fn __action1089< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1090< +fn __action1092< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54057,13 +54137,13 @@ fn __action1090< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action271( + let __temp0 = __action272( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action269( + __action270( mode, __temp0, ) @@ -54071,24 +54151,24 @@ fn __action1090< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1091< +fn __action1093< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), __3: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1090( + let __temp0 = __action1092( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action908( + __action912( mode, __0, __temp0, @@ -54098,22 +54178,22 @@ fn __action1091< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1092< +fn __action1094< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, TextSize, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action270( + let __temp0 = __action271( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action908( + __action912( mode, __0, __temp0, @@ -54123,7 +54203,7 @@ fn __action1092< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1093< +fn __action1095< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54131,12 +54211,12 @@ fn __action1093< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action388( + let __temp0 = __action351( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action391( + __action349( mode, __temp0, ) @@ -54144,7 +54224,7 @@ fn __action1093< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1094< +fn __action1096< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -54153,12 +54233,12 @@ fn __action1094< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action388( + let __temp0 = __action351( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action392( + __action350( mode, __0, __temp0, @@ -54167,7 +54247,51 @@ fn __action1094< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1095< +fn __action1097< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), +) -> alloc::vec::Vec +{ + let __start0 = __0.0; + let __end0 = __0.2; + let __temp0 = __action393( + mode, + __0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action396( + mode, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1098< +>( + mode: Mode, + __0: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, token::Tok, TextSize), +) -> alloc::vec::Vec +{ + let __start0 = __1.0; + let __end0 = __1.2; + let __temp0 = __action393( + mode, + __1, + ); + let __temp0 = (__start0, __temp0, __end0); + __action397( + mode, + __0, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1099< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54177,13 +54301,13 @@ fn __action1095< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action386( + let __temp0 = __action391( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action920( + __action924( mode, __0, __1, @@ -54194,7 +54318,7 @@ fn __action1095< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1096< +fn __action1100< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54205,12 +54329,12 @@ fn __action1096< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action387( + let __temp0 = __action392( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action920( + __action924( mode, __0, __1, @@ -54221,7 +54345,7 @@ fn __action1096< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1097< +fn __action1101< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54230,13 +54354,13 @@ fn __action1097< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action399( + let __temp0 = __action404( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action397( + __action402( mode, __temp0, ) @@ -54244,7 +54368,7 @@ fn __action1097< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1098< +fn __action1102< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -54255,13 +54379,13 @@ fn __action1098< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1097( + let __temp0 = __action1101( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action815( + __action817( mode, __0, __temp0, @@ -54271,7 +54395,7 @@ fn __action1098< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1099< +fn __action1103< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -54280,13 +54404,13 @@ fn __action1099< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action398( + let __temp0 = __action403( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action815( + __action817( mode, __0, __temp0, @@ -54296,7 +54420,7 @@ fn __action1099< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1100< +fn __action1104< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -54307,13 +54431,13 @@ fn __action1100< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1097( + let __temp0 = __action1101( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action816( + __action818( mode, __0, __temp0, @@ -54323,7 +54447,7 @@ fn __action1100< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1101< +fn __action1105< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -54332,13 +54456,13 @@ fn __action1101< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action398( + let __temp0 = __action403( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action816( + __action818( mode, __0, __temp0, @@ -54348,7 +54472,7 @@ fn __action1101< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1102< +fn __action1106< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54373,7 +54497,7 @@ fn __action1102< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1103< +fn __action1107< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54390,14 +54514,14 @@ fn __action1103< { let __start0 = __7.0; let __end0 = __9.2; - let __temp0 = __action1102( + let __temp0 = __action1106( mode, __7, __8, __9, ); let __temp0 = (__start0, __temp0, __end0); - __action800( + __action802( mode, __0, __1, @@ -54412,7 +54536,7 @@ fn __action1103< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1104< +fn __action1108< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54432,7 +54556,7 @@ fn __action1104< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action800( + __action802( mode, __0, __1, @@ -54447,7 +54571,7 @@ fn __action1104< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1105< +fn __action1109< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54463,14 +54587,14 @@ fn __action1105< { let __start0 = __6.0; let __end0 = __8.2; - let __temp0 = __action1102( + let __temp0 = __action1106( mode, __6, __7, __8, ); let __temp0 = (__start0, __temp0, __end0); - __action801( + __action803( mode, __0, __1, @@ -54484,7 +54608,7 @@ fn __action1105< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1106< +fn __action1110< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54503,7 +54627,7 @@ fn __action1106< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action801( + __action803( mode, __0, __1, @@ -54517,7 +54641,7 @@ fn __action1106< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1107< +fn __action1111< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54533,14 +54657,14 @@ fn __action1107< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1102( + let __temp0 = __action1106( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action921( + __action925( mode, __0, __1, @@ -54554,7 +54678,7 @@ fn __action1107< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1108< +fn __action1112< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54573,7 +54697,7 @@ fn __action1108< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action921( + __action925( mode, __0, __1, @@ -54587,7 +54711,7 @@ fn __action1108< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1109< +fn __action1113< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54603,14 +54727,14 @@ fn __action1109< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1102( + let __temp0 = __action1106( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action922( + __action926( mode, __0, __1, @@ -54624,7 +54748,7 @@ fn __action1109< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1110< +fn __action1114< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54643,7 +54767,7 @@ fn __action1110< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action922( + __action926( mode, __0, __1, @@ -54657,7 +54781,7 @@ fn __action1110< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1111< +fn __action1115< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54671,14 +54795,14 @@ fn __action1111< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1102( + let __temp0 = __action1106( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action934( + __action938( mode, __0, __1, @@ -54690,7 +54814,7 @@ fn __action1111< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1112< +fn __action1116< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54707,7 +54831,7 @@ fn __action1112< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action934( + __action938( mode, __0, __1, @@ -54719,7 +54843,7 @@ fn __action1112< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1113< +fn __action1117< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54744,7 +54868,7 @@ fn __action1113< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1114< +fn __action1118< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54764,7 +54888,7 @@ fn __action1114< __5, ); let __temp0 = (__start0, __temp0, __end0); - __action923( + __action927( mode, __0, __1, @@ -54775,7 +54899,7 @@ fn __action1114< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1115< +fn __action1119< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54793,14 +54917,14 @@ fn __action1115< { let __start0 = __7.0; let __end0 = __9.2; - let __temp0 = __action1113( + let __temp0 = __action1117( mode, __7, __8, __9, ); let __temp0 = (__start0, __temp0, __end0); - __action1107( + __action1111( mode, __0, __1, @@ -54816,7 +54940,7 @@ fn __action1115< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1116< +fn __action1120< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54837,7 +54961,7 @@ fn __action1116< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1107( + __action1111( mode, __0, __1, @@ -54853,7 +54977,7 @@ fn __action1116< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1117< +fn __action1121< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54868,14 +54992,14 @@ fn __action1117< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1113( + let __temp0 = __action1117( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action1108( + __action1112( mode, __0, __1, @@ -54888,7 +55012,7 @@ fn __action1117< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1118< +fn __action1122< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54906,7 +55030,7 @@ fn __action1118< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1108( + __action1112( mode, __0, __1, @@ -54919,7 +55043,7 @@ fn __action1118< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1119< +fn __action1123< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54937,14 +55061,14 @@ fn __action1119< { let __start0 = __7.0; let __end0 = __9.2; - let __temp0 = __action1113( + let __temp0 = __action1117( mode, __7, __8, __9, ); let __temp0 = (__start0, __temp0, __end0); - __action1109( + __action1113( mode, __0, __1, @@ -54960,7 +55084,7 @@ fn __action1119< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1120< +fn __action1124< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -54981,7 +55105,7 @@ fn __action1120< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1109( + __action1113( mode, __0, __1, @@ -54997,7 +55121,7 @@ fn __action1120< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1121< +fn __action1125< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55012,14 +55136,14 @@ fn __action1121< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1113( + let __temp0 = __action1117( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action1110( + __action1114( mode, __0, __1, @@ -55032,7 +55156,7 @@ fn __action1121< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1122< +fn __action1126< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55050,7 +55174,7 @@ fn __action1122< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1110( + __action1114( mode, __0, __1, @@ -55063,7 +55187,7 @@ fn __action1122< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1123< +fn __action1127< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55072,13 +55196,13 @@ fn __action1123< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action371( + let __temp0 = __action376( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action369( + __action374( mode, __temp0, ) @@ -55086,7 +55210,7 @@ fn __action1123< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1124< +fn __action1128< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55098,13 +55222,13 @@ fn __action1124< { let __start0 = __2.0; let __end0 = __3.2; - let __temp0 = __action1123( + let __temp0 = __action1127( mode, __2, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action894( + __action898( mode, __0, __1, @@ -55115,7 +55239,7 @@ fn __action1124< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1125< +fn __action1129< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55125,13 +55249,13 @@ fn __action1125< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action370( + let __temp0 = __action375( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action894( + __action898( mode, __0, __1, @@ -55142,7 +55266,7 @@ fn __action1125< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1126< +fn __action1130< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55153,7 +55277,7 @@ fn __action1126< { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action701( + let __temp0 = __action703( mode, __0, __1, @@ -55161,7 +55285,7 @@ fn __action1126< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action404( + __action411( mode, __temp0, ) @@ -55169,7 +55293,7 @@ fn __action1126< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1127< +fn __action1131< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, ast::Expr, ast::Suite)>, TextSize), @@ -55181,7 +55305,7 @@ fn __action1127< { let __start0 = __1.0; let __end0 = __4.2; - let __temp0 = __action701( + let __temp0 = __action703( mode, __1, __2, @@ -55189,7 +55313,7 @@ fn __action1127< __4, ); let __temp0 = (__start0, __temp0, __end0); - __action405( + __action412( mode, __0, __temp0, @@ -55198,7 +55322,7 @@ fn __action1127< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1128< +fn __action1132< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55216,7 +55340,7 @@ fn __action1128< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action814( + __action816( mode, __0, __1, @@ -55229,7 +55353,7 @@ fn __action1128< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1129< +fn __action1133< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55247,7 +55371,7 @@ fn __action1129< __4, ); let __temp0 = (__start0, __temp0, __end0); - __action814( + __action816( mode, __0, __1, @@ -55260,7 +55384,7 @@ fn __action1129< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1130< +fn __action1134< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55270,7 +55394,7 @@ fn __action1130< { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action702( + let __temp0 = __action704( mode, __0, __1, @@ -55285,7 +55409,7 @@ fn __action1130< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1131< +fn __action1135< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55299,14 +55423,14 @@ fn __action1131< { let __start0 = __4.0; let __end0 = __6.2; - let __temp0 = __action1130( + let __temp0 = __action1134( mode, __4, __5, __6, ); let __temp0 = (__start0, __temp0, __end0); - __action1128( + __action1132( mode, __0, __1, @@ -55318,7 +55442,7 @@ fn __action1131< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1132< +fn __action1136< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55335,7 +55459,7 @@ fn __action1132< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1128( + __action1132( mode, __0, __1, @@ -55347,7 +55471,7 @@ fn __action1132< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1133< +fn __action1137< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55362,14 +55486,14 @@ fn __action1133< { let __start0 = __5.0; let __end0 = __7.2; - let __temp0 = __action1130( + let __temp0 = __action1134( mode, __5, __6, __7, ); let __temp0 = (__start0, __temp0, __end0); - __action1129( + __action1133( mode, __0, __1, @@ -55382,7 +55506,7 @@ fn __action1133< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1134< +fn __action1138< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55400,7 +55524,7 @@ fn __action1134< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1129( + __action1133( mode, __0, __1, @@ -55413,7 +55537,7 @@ fn __action1134< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1135< +fn __action1139< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -55422,13 +55546,13 @@ fn __action1135< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action433( + let __temp0 = __action438( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action431( + __action436( mode, __temp0, ) @@ -55436,7 +55560,7 @@ fn __action1135< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1136< +fn __action1140< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -55446,13 +55570,13 @@ fn __action1136< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action433( + let __temp0 = __action438( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action432( + __action437( mode, __0, __temp0, @@ -55461,7 +55585,7 @@ fn __action1136< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1137< +fn __action1141< >( mode: Mode, __0: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), @@ -55470,13 +55594,13 @@ fn __action1137< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action442( + let __temp0 = __action447( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action443( + __action448( mode, __temp0, ) @@ -55484,7 +55608,7 @@ fn __action1137< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1138< +fn __action1142< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -55494,13 +55618,13 @@ fn __action1138< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action442( + let __temp0 = __action447( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action444( + __action449( mode, __0, __temp0, @@ -55509,7 +55633,7 @@ fn __action1138< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1139< +fn __action1143< >( mode: Mode, __0: (TextSize, core::option::Option<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -55517,13 +55641,13 @@ fn __action1139< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action440( + let __temp0 = __action445( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action237( + __action241( mode, __temp0, __0, @@ -55532,7 +55656,7 @@ fn __action1139< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1140< +fn __action1144< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -55541,12 +55665,12 @@ fn __action1140< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action441( + let __temp0 = __action446( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action237( + __action241( mode, __temp0, __1, @@ -55555,7 +55679,7 @@ fn __action1140< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1141< +fn __action1145< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -55564,13 +55688,13 @@ fn __action1141< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action447( + let __temp0 = __action452( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action445( + __action450( mode, __temp0, ) @@ -55578,7 +55702,7 @@ fn __action1141< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1142< +fn __action1146< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -55588,13 +55712,13 @@ fn __action1142< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action447( + let __temp0 = __action452( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action446( + __action451( mode, __0, __temp0, @@ -55603,7 +55727,7 @@ fn __action1142< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1143< +fn __action1147< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -55612,13 +55736,13 @@ fn __action1143< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action547( + let __temp0 = __action550( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action545( + __action548( mode, __temp0, ) @@ -55626,7 +55750,7 @@ fn __action1143< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1144< +fn __action1148< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55640,13 +55764,13 @@ fn __action1144< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1062( + __action1064( mode, __0, __temp0, @@ -55659,7 +55783,7 @@ fn __action1144< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1145< +fn __action1149< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55671,13 +55795,13 @@ fn __action1145< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1062( + __action1064( mode, __0, __temp0, @@ -55690,7 +55814,7 @@ fn __action1145< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1146< +fn __action1150< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55705,13 +55829,13 @@ fn __action1146< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1063( + __action1065( mode, __0, __temp0, @@ -55725,7 +55849,7 @@ fn __action1146< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1147< +fn __action1151< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55738,13 +55862,13 @@ fn __action1147< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1063( + __action1065( mode, __0, __temp0, @@ -55758,7 +55882,7 @@ fn __action1147< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1148< +fn __action1152< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55771,13 +55895,13 @@ fn __action1148< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1064( + __action1066( mode, __0, __temp0, @@ -55789,7 +55913,7 @@ fn __action1148< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1149< +fn __action1153< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55800,13 +55924,13 @@ fn __action1149< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1064( + __action1066( mode, __0, __temp0, @@ -55818,7 +55942,7 @@ fn __action1149< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1150< +fn __action1154< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55832,13 +55956,13 @@ fn __action1150< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1065( + __action1067( mode, __0, __temp0, @@ -55851,7 +55975,7 @@ fn __action1150< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1151< +fn __action1155< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55863,13 +55987,13 @@ fn __action1151< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1065( + __action1067( mode, __0, __temp0, @@ -55882,7 +56006,7 @@ fn __action1151< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1152< +fn __action1156< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55896,13 +56020,13 @@ fn __action1152< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1066( + __action1068( mode, __0, __temp0, @@ -55915,7 +56039,7 @@ fn __action1152< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1153< +fn __action1157< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55927,13 +56051,13 @@ fn __action1153< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1066( + __action1068( mode, __0, __temp0, @@ -55946,7 +56070,7 @@ fn __action1153< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1154< +fn __action1158< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55961,13 +56085,13 @@ fn __action1154< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1067( + __action1069( mode, __0, __temp0, @@ -55981,7 +56105,7 @@ fn __action1154< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1155< +fn __action1159< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -55994,13 +56118,13 @@ fn __action1155< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1067( + __action1069( mode, __0, __temp0, @@ -56014,7 +56138,7 @@ fn __action1155< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1156< +fn __action1160< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56027,13 +56151,13 @@ fn __action1156< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1068( + __action1070( mode, __0, __temp0, @@ -56045,7 +56169,7 @@ fn __action1156< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1157< +fn __action1161< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56056,13 +56180,13 @@ fn __action1157< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1068( + __action1070( mode, __0, __temp0, @@ -56074,7 +56198,7 @@ fn __action1157< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1158< +fn __action1162< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56088,13 +56212,13 @@ fn __action1158< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1143( + let __temp0 = __action1147( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1069( + __action1071( mode, __0, __temp0, @@ -56107,7 +56231,7 @@ fn __action1158< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1159< +fn __action1163< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56119,13 +56243,13 @@ fn __action1159< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action546( + let __temp0 = __action549( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1069( + __action1071( mode, __0, __temp0, @@ -56138,7 +56262,7 @@ fn __action1159< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1160< +fn __action1164< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -56161,7 +56285,7 @@ fn __action1160< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1161< +fn __action1165< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56186,7 +56310,7 @@ fn __action1161< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1162< +fn __action1166< >( mode: Mode, __0: (TextSize, core::option::Option, TextSize), @@ -56194,7 +56318,7 @@ fn __action1162< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action402( + let __temp0 = __action409( mode, &__start0, &__end0, @@ -56209,7 +56333,7 @@ fn __action1162< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1163< +fn __action1167< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56218,7 +56342,7 @@ fn __action1163< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action403( + let __temp0 = __action410( mode, __0, ); @@ -56232,7 +56356,7 @@ fn __action1163< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1164< +fn __action1168< >( mode: Mode, __0: (TextSize, ast::Stmt, TextSize), @@ -56241,13 +56365,13 @@ fn __action1164< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action385( + let __temp0 = __action390( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action393( + __action398( mode, __temp0, ) @@ -56255,7 +56379,7 @@ fn __action1164< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1165< +fn __action1169< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56265,13 +56389,13 @@ fn __action1165< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action385( + let __temp0 = __action390( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action394( + __action399( mode, __0, __temp0, @@ -56280,7 +56404,7 @@ fn __action1165< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1166< +fn __action1170< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -56291,13 +56415,13 @@ fn __action1166< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action648( + __action653( mode, __0, __temp0, @@ -56309,7 +56433,7 @@ fn __action1166< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1167< +fn __action1171< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -56321,12 +56445,12 @@ fn __action1167< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action648( + __action653( mode, __0, __temp0, @@ -56338,7 +56462,7 @@ fn __action1167< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1168< +fn __action1172< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -56348,13 +56472,13 @@ fn __action1168< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action649( + __action654( mode, __0, __temp0, @@ -56365,7 +56489,7 @@ fn __action1168< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1169< +fn __action1173< >( mode: Mode, __0: (TextSize, ast::Suite, TextSize), @@ -56376,12 +56500,12 @@ fn __action1169< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action649( + __action654( mode, __0, __temp0, @@ -56392,7 +56516,7 @@ fn __action1169< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1170< +fn __action1174< >( mode: Mode, __0: (TextSize, ast::Stmt, TextSize), @@ -56402,13 +56526,13 @@ fn __action1170< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action650( + __action655( mode, __temp0, __0, @@ -56419,7 +56543,7 @@ fn __action1170< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1171< +fn __action1175< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56430,12 +56554,12 @@ fn __action1171< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action650( + __action655( mode, __temp0, __1, @@ -56446,7 +56570,7 @@ fn __action1171< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1172< +fn __action1176< >( mode: Mode, __0: (TextSize, ast::Stmt, TextSize), @@ -56455,13 +56579,13 @@ fn __action1172< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action651( + __action656( mode, __temp0, __0, @@ -56471,7 +56595,7 @@ fn __action1172< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1173< +fn __action1177< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56481,12 +56605,12 @@ fn __action1173< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action651( + __action656( mode, __temp0, __1, @@ -56496,7 +56620,7 @@ fn __action1173< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1174< +fn __action1178< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -56507,13 +56631,13 @@ fn __action1174< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action652( + __action657( mode, __0, __temp0, @@ -56525,7 +56649,7 @@ fn __action1174< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1175< +fn __action1179< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -56537,12 +56661,12 @@ fn __action1175< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action652( + __action657( mode, __0, __temp0, @@ -56554,7 +56678,7 @@ fn __action1175< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1176< +fn __action1180< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -56564,13 +56688,13 @@ fn __action1176< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action653( + __action658( mode, __0, __temp0, @@ -56581,7 +56705,7 @@ fn __action1176< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1177< +fn __action1181< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -56592,12 +56716,12 @@ fn __action1177< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action653( + __action658( mode, __0, __temp0, @@ -56608,7 +56732,7 @@ fn __action1177< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1178< +fn __action1182< >( mode: Mode, __0: (TextSize, ast::Stmt, TextSize), @@ -56618,13 +56742,13 @@ fn __action1178< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action654( + __action659( mode, __temp0, __0, @@ -56635,7 +56759,7 @@ fn __action1178< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1179< +fn __action1183< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56646,12 +56770,12 @@ fn __action1179< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action654( + __action659( mode, __temp0, __1, @@ -56662,7 +56786,7 @@ fn __action1179< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1180< +fn __action1184< >( mode: Mode, __0: (TextSize, ast::Stmt, TextSize), @@ -56671,13 +56795,13 @@ fn __action1180< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action383( + let __temp0 = __action388( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action655( + __action660( mode, __temp0, __0, @@ -56687,7 +56811,7 @@ fn __action1180< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1181< +fn __action1185< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56697,12 +56821,12 @@ fn __action1181< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action384( + let __temp0 = __action389( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action655( + __action660( mode, __temp0, __1, @@ -56712,7 +56836,7 @@ fn __action1181< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1182< +fn __action1186< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56732,7 +56856,7 @@ fn __action1182< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action786( + __action788( mode, __0, __temp0, @@ -56743,7 +56867,7 @@ fn __action1182< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1183< +fn __action1187< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -56764,7 +56888,7 @@ fn __action1183< __4, ); let __temp0 = (__start0, __temp0, __end0); - __action788( + __action790( mode, __0, __1, @@ -56776,7 +56900,7 @@ fn __action1183< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1184< +fn __action1188< >( mode: Mode, __0: (TextSize, (String, StringKind, bool), TextSize), @@ -56784,13 +56908,13 @@ fn __action1184< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action703( + __action705( mode, __0, __temp0, @@ -56799,7 +56923,7 @@ fn __action1184< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1185< +fn __action1189< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -56809,13 +56933,13 @@ fn __action1185< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action704( + __action706( mode, __0, __1, @@ -56826,7 +56950,7 @@ fn __action1185< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1186< +fn __action1190< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -56836,13 +56960,13 @@ fn __action1186< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action705( + __action707( mode, __0, __1, @@ -56853,7 +56977,7 @@ fn __action1186< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1187< +fn __action1191< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -56863,13 +56987,13 @@ fn __action1187< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action706( + __action708( mode, __0, __1, @@ -56880,7 +57004,7 @@ fn __action1187< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1188< +fn __action1192< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56889,13 +57013,13 @@ fn __action1188< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action707( + __action709( mode, __0, __1, @@ -56905,7 +57029,7 @@ fn __action1188< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1189< +fn __action1193< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -56914,13 +57038,13 @@ fn __action1189< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action708( + __action710( mode, __0, __1, @@ -56930,7 +57054,34 @@ fn __action1189< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1190< +fn __action1194< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), + __2: (TextSize, token::Tok, TextSize), +) -> Result> +{ + let __start0 = __2.2; + let __end0 = __2.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action711( + mode, + __0, + __1, + __2, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1195< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -56940,13 +57091,13 @@ fn __action1190< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action709( + __action712( mode, __0, __1, @@ -56957,7 +57108,7 @@ fn __action1190< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1191< +fn __action1196< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -56967,13 +57118,13 @@ fn __action1191< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action710( + __action713( mode, __0, __1, @@ -56984,7 +57135,7 @@ fn __action1191< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1192< +fn __action1197< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -56994,13 +57145,13 @@ fn __action1192< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action711( + __action714( mode, __0, __1, @@ -57011,7 +57162,7 @@ fn __action1192< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1193< +fn __action1198< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57022,13 +57173,13 @@ fn __action1193< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1058( + __action1060( mode, __0, __1, @@ -57040,7 +57191,7 @@ fn __action1193< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1194< +fn __action1199< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57049,13 +57200,13 @@ fn __action1194< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1059( + __action1061( mode, __0, __1, @@ -57065,7 +57216,7 @@ fn __action1194< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1195< +fn __action1200< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -57073,13 +57224,13 @@ fn __action1195< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action714( + __action717( mode, __0, __temp0, @@ -57088,7 +57239,7 @@ fn __action1195< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1196< +fn __action1201< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -57096,13 +57247,13 @@ fn __action1196< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action715( + __action718( mode, __0, __temp0, @@ -57111,7 +57262,7 @@ fn __action1196< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1197< +fn __action1202< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57121,13 +57272,13 @@ fn __action1197< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action716( + __action719( mode, __0, __1, @@ -57138,7 +57289,7 @@ fn __action1197< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1198< +fn __action1203< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57149,13 +57300,13 @@ fn __action1198< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action717( + __action720( mode, __0, __1, @@ -57167,7 +57318,7 @@ fn __action1198< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1199< +fn __action1204< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57178,13 +57329,13 @@ fn __action1199< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action718( + __action721( mode, __0, __1, @@ -57196,7 +57347,7 @@ fn __action1199< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1200< +fn __action1205< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57206,13 +57357,13 @@ fn __action1200< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action719( + __action722( mode, __0, __1, @@ -57223,7 +57374,7 @@ fn __action1200< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1201< +fn __action1206< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57236,13 +57387,13 @@ fn __action1201< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1144( + __action1148( mode, __0, __1, @@ -57256,7 +57407,7 @@ fn __action1201< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1202< +fn __action1207< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57267,13 +57418,13 @@ fn __action1202< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1145( + __action1149( mode, __0, __1, @@ -57285,7 +57436,7 @@ fn __action1202< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1203< +fn __action1208< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57299,13 +57450,13 @@ fn __action1203< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1146( + __action1150( mode, __0, __1, @@ -57320,7 +57471,7 @@ fn __action1203< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1204< +fn __action1209< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57332,13 +57483,13 @@ fn __action1204< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1147( + __action1151( mode, __0, __1, @@ -57351,7 +57502,7 @@ fn __action1204< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1205< +fn __action1210< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57363,13 +57514,13 @@ fn __action1205< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1148( + __action1152( mode, __0, __1, @@ -57382,7 +57533,7 @@ fn __action1205< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1206< +fn __action1211< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57392,13 +57543,13 @@ fn __action1206< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1149( + __action1153( mode, __0, __1, @@ -57409,7 +57560,7 @@ fn __action1206< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1207< +fn __action1212< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57422,13 +57573,13 @@ fn __action1207< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1150( + __action1154( mode, __0, __1, @@ -57442,7 +57593,7 @@ fn __action1207< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1208< +fn __action1213< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57453,13 +57604,13 @@ fn __action1208< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1151( + __action1155( mode, __0, __1, @@ -57471,7 +57622,7 @@ fn __action1208< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1209< +fn __action1214< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57480,13 +57631,13 @@ fn __action1209< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action722( + __action725( mode, __0, __1, @@ -57496,7 +57647,7 @@ fn __action1209< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1210< +fn __action1215< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57507,13 +57658,13 @@ fn __action1210< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action723( + __action726( mode, __0, __1, @@ -57525,7 +57676,7 @@ fn __action1210< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1211< +fn __action1216< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57536,13 +57687,13 @@ fn __action1211< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action724( + __action727( mode, __0, __1, @@ -57554,7 +57705,7 @@ fn __action1211< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1212< +fn __action1217< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57564,13 +57715,13 @@ fn __action1212< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action725( + __action728( mode, __0, __1, @@ -57581,7 +57732,7 @@ fn __action1212< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1213< +fn __action1218< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57592,13 +57743,13 @@ fn __action1213< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action726( + __action729( mode, __0, __1, @@ -57610,7 +57761,7 @@ fn __action1213< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1214< +fn __action1219< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57620,13 +57771,13 @@ fn __action1214< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action727( + __action730( mode, __0, __1, @@ -57637,7 +57788,7 @@ fn __action1214< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1215< +fn __action1220< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57648,13 +57799,13 @@ fn __action1215< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action728( + __action731( mode, __0, __1, @@ -57666,7 +57817,7 @@ fn __action1215< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1216< +fn __action1221< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57674,13 +57825,13 @@ fn __action1216< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action729( + __action732( mode, __0, __temp0, @@ -57689,7 +57840,7 @@ fn __action1216< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1217< +fn __action1222< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57697,13 +57848,13 @@ fn __action1217< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action730( + __action733( mode, __0, __temp0, @@ -57712,7 +57863,7 @@ fn __action1217< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1218< +fn __action1223< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57720,13 +57871,13 @@ fn __action1218< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action731( + __action734( mode, __0, __temp0, @@ -57735,7 +57886,7 @@ fn __action1218< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1219< +fn __action1224< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57743,13 +57894,13 @@ fn __action1219< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action732( + __action735( mode, __0, __temp0, @@ -57758,7 +57909,7 @@ fn __action1219< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1220< +fn __action1225< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -57766,13 +57917,13 @@ fn __action1220< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action734( + __action737( mode, __0, __temp0, @@ -57781,7 +57932,7 @@ fn __action1220< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1221< +fn __action1226< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -57789,13 +57940,13 @@ fn __action1221< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action735( + __action738( mode, __0, __temp0, @@ -57804,7 +57955,7 @@ fn __action1221< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1222< +fn __action1227< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57814,13 +57965,13 @@ fn __action1222< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action736( + __action739( mode, __0, __1, @@ -57831,7 +57982,7 @@ fn __action1222< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1223< +fn __action1228< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57842,13 +57993,13 @@ fn __action1223< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action737( + __action740( mode, __0, __1, @@ -57860,7 +58011,7 @@ fn __action1223< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1224< +fn __action1229< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57873,13 +58024,13 @@ fn __action1224< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1152( + __action1156( mode, __0, __1, @@ -57893,7 +58044,7 @@ fn __action1224< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1225< +fn __action1230< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57904,13 +58055,13 @@ fn __action1225< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1153( + __action1157( mode, __0, __1, @@ -57922,7 +58073,7 @@ fn __action1225< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1226< +fn __action1231< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57936,13 +58087,13 @@ fn __action1226< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1154( + __action1158( mode, __0, __1, @@ -57957,7 +58108,7 @@ fn __action1226< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1227< +fn __action1232< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -57969,13 +58120,13 @@ fn __action1227< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1155( + __action1159( mode, __0, __1, @@ -57988,7 +58139,7 @@ fn __action1227< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1228< +fn __action1233< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58000,13 +58151,13 @@ fn __action1228< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1156( + __action1160( mode, __0, __1, @@ -58019,7 +58170,7 @@ fn __action1228< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1229< +fn __action1234< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58029,13 +58180,13 @@ fn __action1229< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1157( + __action1161( mode, __0, __1, @@ -58046,7 +58197,7 @@ fn __action1229< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1230< +fn __action1235< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58059,13 +58210,13 @@ fn __action1230< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1158( + __action1162( mode, __0, __1, @@ -58079,7 +58230,7 @@ fn __action1230< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1231< +fn __action1236< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58090,13 +58241,13 @@ fn __action1231< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1159( + __action1163( mode, __0, __1, @@ -58108,7 +58259,7 @@ fn __action1231< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1232< +fn __action1237< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58117,13 +58268,13 @@ fn __action1232< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action740( + __action743( mode, __0, __1, @@ -58133,7 +58284,7 @@ fn __action1232< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1233< +fn __action1238< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58144,13 +58295,13 @@ fn __action1233< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action741( + __action744( mode, __0, __1, @@ -58162,7 +58313,7 @@ fn __action1233< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1234< +fn __action1239< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58173,13 +58324,13 @@ fn __action1234< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action742( + __action745( mode, __0, __1, @@ -58191,7 +58342,7 @@ fn __action1234< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1235< +fn __action1240< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58201,13 +58352,13 @@ fn __action1235< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action743( + __action746( mode, __0, __1, @@ -58218,7 +58369,7 @@ fn __action1235< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1236< +fn __action1241< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58229,13 +58380,13 @@ fn __action1236< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action744( + __action747( mode, __0, __1, @@ -58247,7 +58398,7 @@ fn __action1236< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1237< +fn __action1242< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58257,13 +58408,13 @@ fn __action1237< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action745( + __action748( mode, __0, __1, @@ -58274,7 +58425,7 @@ fn __action1237< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1238< +fn __action1243< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58285,13 +58436,13 @@ fn __action1238< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action746( + __action749( mode, __0, __1, @@ -58303,7 +58454,7 @@ fn __action1238< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1239< +fn __action1244< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58311,13 +58462,13 @@ fn __action1239< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action747( + __action750( mode, __0, __temp0, @@ -58326,7 +58477,7 @@ fn __action1239< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1240< +fn __action1245< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58334,13 +58485,13 @@ fn __action1240< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action748( + __action751( mode, __0, __temp0, @@ -58349,7 +58500,7 @@ fn __action1240< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1241< +fn __action1246< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58357,13 +58508,13 @@ fn __action1241< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action749( + __action752( mode, __0, __temp0, @@ -58372,7 +58523,7 @@ fn __action1241< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1242< +fn __action1247< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58380,13 +58531,13 @@ fn __action1242< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action750( + __action753( mode, __0, __temp0, @@ -58395,36 +58546,32 @@ fn __action1242< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1243< +fn __action1248< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ArgumentList, TextSize), - __3: (TextSize, token::Tok, TextSize), + __1: (TextSize, ast::Arguments, TextSize), ) -> ast::Expr { - let __start0 = __3.2; - let __end0 = __3.2; - let __temp0 = __action389( + let __start0 = __1.2; + let __end0 = __1.2; + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action751( + __action754( mode, __0, __1, - __2, - __3, __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1244< +fn __action1249< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58435,13 +58582,13 @@ fn __action1244< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action752( + __action755( mode, __0, __1, @@ -58453,7 +58600,7 @@ fn __action1244< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1245< +fn __action1250< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58463,13 +58610,13 @@ fn __action1245< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action753( + __action756( mode, __0, __1, @@ -58480,36 +58627,32 @@ fn __action1245< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1246< +fn __action1251< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ArgumentList, TextSize), - __3: (TextSize, token::Tok, TextSize), + __1: (TextSize, ast::Arguments, TextSize), ) -> ast::Expr { - let __start0 = __3.2; - let __end0 = __3.2; - let __temp0 = __action389( + let __start0 = __1.2; + let __end0 = __1.2; + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action754( + __action757( mode, __0, __1, - __2, - __3, __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1247< +fn __action1252< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58520,13 +58663,13 @@ fn __action1247< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action755( + __action758( mode, __0, __1, @@ -58538,7 +58681,7 @@ fn __action1247< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1248< +fn __action1253< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58548,13 +58691,13 @@ fn __action1248< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action756( + __action759( mode, __0, __1, @@ -58565,7 +58708,7 @@ fn __action1248< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1249< +fn __action1254< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58574,13 +58717,13 @@ fn __action1249< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action757( + __action760( mode, __0, __1, @@ -58590,7 +58733,7 @@ fn __action1249< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1250< +fn __action1255< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -58599,13 +58742,13 @@ fn __action1250< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action758( + __action761( mode, __0, __1, @@ -58615,7 +58758,7 @@ fn __action1250< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1251< +fn __action1256< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -58623,13 +58766,13 @@ fn __action1251< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action759( + __action762( mode, __0, __temp0, @@ -58638,7 +58781,7 @@ fn __action1251< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1252< +fn __action1257< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58652,13 +58795,13 @@ fn __action1252< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action762( + __action764( mode, __0, __1, @@ -58673,7 +58816,7 @@ fn __action1252< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1253< +fn __action1258< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58686,13 +58829,13 @@ fn __action1253< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action763( + __action765( mode, __0, __1, @@ -58706,7 +58849,7 @@ fn __action1253< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1254< +fn __action1259< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58718,13 +58861,13 @@ fn __action1254< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action764( + __action766( mode, __0, __1, @@ -58737,7 +58880,7 @@ fn __action1254< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1255< +fn __action1260< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58748,13 +58891,13 @@ fn __action1255< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action765( + __action767( mode, __0, __1, @@ -58766,7 +58909,7 @@ fn __action1255< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1256< +fn __action1261< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58778,13 +58921,13 @@ fn __action1256< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action766( + __action768( mode, __0, __1, @@ -58797,7 +58940,7 @@ fn __action1256< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1257< +fn __action1262< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58808,13 +58951,13 @@ fn __action1257< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action767( + __action769( mode, __0, __1, @@ -58826,7 +58969,7 @@ fn __action1257< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1258< +fn __action1263< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58836,13 +58979,13 @@ fn __action1258< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action768( + __action770( mode, __0, __1, @@ -58853,7 +58996,7 @@ fn __action1258< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1259< +fn __action1264< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58867,13 +59010,13 @@ fn __action1259< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action769( + __action771( mode, __0, __1, @@ -58888,7 +59031,7 @@ fn __action1259< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1260< +fn __action1265< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58901,13 +59044,13 @@ fn __action1260< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action770( + __action772( mode, __0, __1, @@ -58921,7 +59064,7 @@ fn __action1260< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1261< +fn __action1266< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58933,13 +59076,13 @@ fn __action1261< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action771( + __action773( mode, __0, __1, @@ -58952,7 +59095,7 @@ fn __action1261< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1262< +fn __action1267< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58963,13 +59106,13 @@ fn __action1262< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action772( + __action774( mode, __0, __1, @@ -58981,7 +59124,7 @@ fn __action1262< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1263< +fn __action1268< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -58993,13 +59136,13 @@ fn __action1263< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action773( + __action775( mode, __0, __1, @@ -59012,7 +59155,7 @@ fn __action1263< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1264< +fn __action1269< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59023,13 +59166,13 @@ fn __action1264< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action774( + __action776( mode, __0, __1, @@ -59041,7 +59184,7 @@ fn __action1264< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1265< +fn __action1270< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59051,13 +59194,13 @@ fn __action1265< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action775( + __action777( mode, __0, __1, @@ -59068,7 +59211,7 @@ fn __action1265< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1266< +fn __action1271< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59077,13 +59220,13 @@ fn __action1266< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action776( + __action778( mode, __0, __1, @@ -59093,7 +59236,7 @@ fn __action1266< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1267< +fn __action1272< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59102,13 +59245,13 @@ fn __action1267< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action777( + __action779( mode, __0, __1, @@ -59118,7 +59261,7 @@ fn __action1267< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1268< +fn __action1273< >( mode: Mode, __0: (TextSize, ast::Constant, TextSize), @@ -59126,13 +59269,13 @@ fn __action1268< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action778( + __action780( mode, __0, __temp0, @@ -59141,7 +59284,7 @@ fn __action1268< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1269< +fn __action1274< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59150,13 +59293,13 @@ fn __action1269< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action779( + __action781( mode, __0, __1, @@ -59166,7 +59309,7 @@ fn __action1269< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1270< +fn __action1275< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59176,13 +59319,13 @@ fn __action1270< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action780( + __action782( mode, __0, __1, @@ -59193,7 +59336,7 @@ fn __action1270< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1271< +fn __action1276< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59202,13 +59345,13 @@ fn __action1271< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action781( + __action783( mode, __0, __1, @@ -59218,7 +59361,7 @@ fn __action1271< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1272< +fn __action1277< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -59226,13 +59369,13 @@ fn __action1272< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action782( + __action784( mode, __0, __temp0, @@ -59241,7 +59384,7 @@ fn __action1272< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1273< +fn __action1278< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -59250,13 +59393,13 @@ fn __action1273< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action783( + __action785( mode, __0, __1, @@ -59266,23 +59409,23 @@ fn __action1273< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1274< +fn __action1279< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1084( + __action1086( mode, __0, __1, @@ -59293,21 +59436,21 @@ fn __action1274< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1275< +fn __action1280< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1085( + __action1087( mode, __0, __temp0, @@ -59316,7 +59459,7 @@ fn __action1275< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1276< +fn __action1281< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59326,13 +59469,13 @@ fn __action1276< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action789( + __action791( mode, __0, __1, @@ -59343,7 +59486,7 @@ fn __action1276< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1277< +fn __action1282< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59353,13 +59496,13 @@ fn __action1277< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action790( + __action792( mode, __0, __1, @@ -59370,7 +59513,7 @@ fn __action1277< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1278< +fn __action1283< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59379,13 +59522,13 @@ fn __action1278< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action791( + __action793( mode, __0, __1, @@ -59395,7 +59538,7 @@ fn __action1278< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1279< +fn __action1284< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59405,13 +59548,13 @@ fn __action1279< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action792( + __action794( mode, __0, __1, @@ -59422,7 +59565,7 @@ fn __action1279< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1280< +fn __action1285< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59433,13 +59576,13 @@ fn __action1280< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action793( + __action795( mode, __0, __1, @@ -59451,7 +59594,7 @@ fn __action1280< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1281< +fn __action1286< >( mode: Mode, __0: (TextSize, ast::UnaryOp, TextSize), @@ -59460,13 +59603,13 @@ fn __action1281< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action794( + __action796( mode, __0, __1, @@ -59476,7 +59619,7 @@ fn __action1281< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1282< +fn __action1287< >( mode: Mode, __0: (TextSize, ast::UnaryOp, TextSize), @@ -59485,13 +59628,13 @@ fn __action1282< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action795( + __action797( mode, __0, __1, @@ -59501,7 +59644,7 @@ fn __action1282< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1283< +fn __action1288< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59509,13 +59652,13 @@ fn __action1283< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action796( + __action798( mode, __0, __temp0, @@ -59524,7 +59667,7 @@ fn __action1283< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1284< +fn __action1289< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59532,13 +59675,13 @@ fn __action1284< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action797( + __action799( mode, __0, __temp0, @@ -59547,7 +59690,7 @@ fn __action1284< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1285< +fn __action1290< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59556,13 +59699,13 @@ fn __action1285< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action798( + __action800( mode, __0, __1, @@ -59572,7 +59715,7 @@ fn __action1285< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1286< +fn __action1291< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59580,13 +59723,13 @@ fn __action1286< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action799( + __action801( mode, __0, __temp0, @@ -59595,7 +59738,7 @@ fn __action1286< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1287< +fn __action1292< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -59604,13 +59747,13 @@ fn __action1287< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action804( + __action806( mode, __0, __1, @@ -59620,7 +59763,7 @@ fn __action1287< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1288< +fn __action1293< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -59630,13 +59773,13 @@ fn __action1288< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action805( + __action807( mode, __0, __1, @@ -59647,7 +59790,7 @@ fn __action1288< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1289< +fn __action1294< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59656,13 +59799,13 @@ fn __action1289< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action806( + __action808( mode, __0, __1, @@ -59672,7 +59815,7 @@ fn __action1289< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1290< +fn __action1295< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59681,13 +59824,13 @@ fn __action1290< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action807( + __action809( mode, __0, __1, @@ -59697,7 +59840,7 @@ fn __action1290< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1291< +fn __action1296< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -59706,13 +59849,13 @@ fn __action1291< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action808( + __action810( mode, __0, __1, @@ -59722,7 +59865,7 @@ fn __action1291< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1292< +fn __action1297< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -59730,13 +59873,13 @@ fn __action1292< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action809( + __action811( mode, __0, __temp0, @@ -59745,7 +59888,7 @@ fn __action1292< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1293< +fn __action1298< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -59754,13 +59897,13 @@ fn __action1293< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action810( + __action812( mode, __0, __1, @@ -59770,7 +59913,7 @@ fn __action1293< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1294< +fn __action1299< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -59778,13 +59921,13 @@ fn __action1294< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action811( + __action813( mode, __0, __temp0, @@ -59793,7 +59936,7 @@ fn __action1294< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1295< +fn __action1300< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59802,13 +59945,13 @@ fn __action1295< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action812( + __action814( mode, __0, __1, @@ -59818,7 +59961,7 @@ fn __action1295< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1296< +fn __action1301< >( mode: Mode, __0: (TextSize, String, TextSize), @@ -59826,13 +59969,13 @@ fn __action1296< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action813( + __action815( mode, __0, __temp0, @@ -59841,7 +59984,7 @@ fn __action1296< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1297< +fn __action1302< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -59851,13 +59994,13 @@ fn __action1297< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1098( + __action1102( mode, __0, __1, @@ -59868,7 +60011,7 @@ fn __action1297< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1298< +fn __action1303< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -59876,13 +60019,13 @@ fn __action1298< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1099( + __action1103( mode, __0, __temp0, @@ -59891,7 +60034,7 @@ fn __action1298< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1299< +fn __action1304< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -59901,13 +60044,13 @@ fn __action1299< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1100( + __action1104( mode, __0, __1, @@ -59918,7 +60061,7 @@ fn __action1299< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1300< +fn __action1305< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -59926,13 +60069,13 @@ fn __action1300< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1101( + __action1105( mode, __0, __temp0, @@ -59941,7 +60084,7 @@ fn __action1300< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1301< +fn __action1306< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -59949,13 +60092,13 @@ fn __action1301< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action817( + __action819( mode, __0, __temp0, @@ -59964,7 +60107,7 @@ fn __action1301< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1302< +fn __action1307< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -59975,13 +60118,13 @@ fn __action1302< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action818( + __action820( mode, __0, __1, @@ -59993,7 +60136,7 @@ fn __action1302< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1303< +fn __action1308< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60003,13 +60146,13 @@ fn __action1303< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action819( + __action821( mode, __0, __1, @@ -60020,7 +60163,7 @@ fn __action1303< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1304< +fn __action1309< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60028,13 +60171,13 @@ fn __action1304< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action820( + __action822( mode, __0, __temp0, @@ -60043,7 +60186,7 @@ fn __action1304< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1305< +fn __action1310< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60052,13 +60195,13 @@ fn __action1305< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action821( + __action823( mode, __0, __1, @@ -60068,7 +60211,7 @@ fn __action1305< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1306< +fn __action1311< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60079,13 +60222,13 @@ fn __action1306< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action822( + __action824( mode, __0, __1, @@ -60097,59 +60240,44 @@ fn __action1306< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1307< +fn __action1312< >( mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), - __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Expr, TextSize), + __0: (TextSize, (IpyEscapeKind, String), TextSize), ) -> Result> { - let __start0 = __1.2; - let __end0 = __2.0; - let __start1 = __3.2; - let __end1 = __3.2; - let __temp0 = __action389( + let __start0 = __0.2; + let __end0 = __0.2; + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - let __temp1 = __action389( - mode, - &__start1, - &__end1, - ); - let __temp1 = (__start1, __temp1, __end1); - __action823( + __action825( mode, __0, - __1, __temp0, - __2, - __3, - __temp1, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1308< +fn __action1313< >( mode: Mode, - __0: (TextSize, (MagicKind, String), TextSize), -) -> Result> + __0: (TextSize, (IpyEscapeKind, String), TextSize), +) -> Result> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action824( + __action826( mode, __0, __temp0, @@ -60158,30 +60286,70 @@ fn __action1308< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1309< +fn __action1314< >( mode: Mode, - __0: (TextSize, (MagicKind, String), TextSize), + __0: (TextSize, ast::Expr, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), ) -> Result> { - let __start0 = __0.2; - let __end0 = __0.2; - let __temp0 = __action389( + let __start0 = __1.2; + let __end0 = __1.2; + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action825( + __action827( mode, __0, + __1, __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1310< +fn __action1315< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, core::option::Option, TextSize), + __2: (TextSize, token::Tok, TextSize), + __3: (TextSize, ast::Expr, TextSize), +) -> Result> +{ + let __start0 = __1.2; + let __end0 = __2.0; + let __start1 = __3.2; + let __end1 = __3.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + let __temp1 = __action394( + mode, + &__start1, + &__end1, + ); + let __temp1 = (__start1, __temp1, __end1); + __action828( + mode, + __0, + __1, + __temp0, + __2, + __3, + __temp1, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1316< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60189,13 +60357,13 @@ fn __action1310< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action826( + __action829( mode, __0, __temp0, @@ -60204,7 +60372,7 @@ fn __action1310< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1311< +fn __action1317< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60212,13 +60380,13 @@ fn __action1311< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action827( + __action830( mode, __0, __temp0, @@ -60227,7 +60395,7 @@ fn __action1311< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1312< +fn __action1318< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60235,13 +60403,13 @@ fn __action1312< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action828( + __action831( mode, __0, __temp0, @@ -60250,7 +60418,7 @@ fn __action1312< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1313< +fn __action1319< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -60258,13 +60426,13 @@ fn __action1313< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action829( + __action832( mode, __0, __temp0, @@ -60273,7 +60441,7 @@ fn __action1313< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1314< +fn __action1320< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -60281,13 +60449,13 @@ fn __action1314< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action830( + __action833( mode, __0, __temp0, @@ -60296,7 +60464,7 @@ fn __action1314< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1315< +fn __action1321< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -60304,13 +60472,13 @@ fn __action1315< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action831( + __action834( mode, __0, __temp0, @@ -60319,7 +60487,7 @@ fn __action1315< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1316< +fn __action1322< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60327,13 +60495,13 @@ fn __action1316< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action832( + __action835( mode, __0, __temp0, @@ -60342,7 +60510,7 @@ fn __action1316< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1317< +fn __action1323< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60350,13 +60518,13 @@ fn __action1317< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action833( + __action836( mode, __0, __temp0, @@ -60365,7 +60533,7 @@ fn __action1317< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1318< +fn __action1324< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60373,13 +60541,13 @@ fn __action1318< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action834( + __action837( mode, __0, __temp0, @@ -60388,7 +60556,7 @@ fn __action1318< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1319< +fn __action1325< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60397,13 +60565,13 @@ fn __action1319< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action836( + __action839( mode, __0, __1, @@ -60413,7 +60581,7 @@ fn __action1319< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1320< +fn __action1326< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60424,13 +60592,13 @@ fn __action1320< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action837( + __action840( mode, __0, __1, @@ -60442,7 +60610,7 @@ fn __action1320< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1321< +fn __action1327< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60452,13 +60620,13 @@ fn __action1321< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action838( + __action841( mode, __0, __1, @@ -60469,7 +60637,7 @@ fn __action1321< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1322< +fn __action1328< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60481,13 +60649,13 @@ fn __action1322< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action839( + __action842( mode, __0, __1, @@ -60500,7 +60668,7 @@ fn __action1322< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1323< +fn __action1329< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60511,13 +60679,13 @@ fn __action1323< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action840( + __action843( mode, __0, __1, @@ -60529,7 +60697,7 @@ fn __action1323< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1324< +fn __action1330< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60543,13 +60711,13 @@ fn __action1324< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action841( + __action844( mode, __0, __1, @@ -60564,7 +60732,7 @@ fn __action1324< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1325< +fn __action1331< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60577,13 +60745,13 @@ fn __action1325< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action842( + __action845( mode, __0, __1, @@ -60597,7 +60765,7 @@ fn __action1325< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1326< +fn __action1332< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -60605,13 +60773,13 @@ fn __action1326< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action844( + __action847( mode, __0, __temp0, @@ -60620,7 +60788,7 @@ fn __action1326< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1327< +fn __action1333< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -60630,13 +60798,13 @@ fn __action1327< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action845( + __action848( mode, __0, __1, @@ -60647,7 +60815,7 @@ fn __action1327< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1328< +fn __action1334< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -60657,13 +60825,13 @@ fn __action1328< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action846( + __action849( mode, __0, __1, @@ -60674,34 +60842,57 @@ fn __action1328< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1329< +fn __action1335< >( mode: Mode, - __0: (TextSize, ast::Identifier, TextSize), + __0: (TextSize, ast::Expr, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), ) -> ast::Expr { - let __start0 = __0.2; - let __end0 = __1.0; - let __temp0 = __action389( + let __start0 = __2.2; + let __end0 = __2.2; + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action851( + __action854( mode, __0, - __temp0, __1, __2, + __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1330< +fn __action1336< +>( + mode: Mode, + __0: (TextSize, ast::Identifier, TextSize), +) -> ast::Expr +{ + let __start0 = __0.2; + let __end0 = __0.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action855( + mode, + __0, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1337< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60710,13 +60901,13 @@ fn __action1330< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action852( + __action856( mode, __0, __1, @@ -60726,7 +60917,7 @@ fn __action1330< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1331< +fn __action1338< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60735,13 +60926,13 @@ fn __action1331< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action853( + __action857( mode, __0, __1, @@ -60751,7 +60942,7 @@ fn __action1331< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1332< +fn __action1339< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -60760,13 +60951,13 @@ fn __action1332< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action854( + __action858( mode, __0, __1, @@ -60776,7 +60967,7 @@ fn __action1332< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1333< +fn __action1340< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -60784,13 +60975,13 @@ fn __action1333< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action855( + __action859( mode, __0, __temp0, @@ -60799,7 +60990,7 @@ fn __action1333< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1334< +fn __action1341< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -60808,13 +60999,13 @@ fn __action1334< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action856( + __action860( mode, __0, __1, @@ -60824,7 +61015,7 @@ fn __action1334< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1335< +fn __action1342< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -60833,13 +61024,13 @@ fn __action1335< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action857( + __action861( mode, __0, __1, @@ -60849,23 +61040,23 @@ fn __action1335< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1336< +fn __action1343< >( mode: Mode, - __0: (TextSize, ast::ArgWithDefault, TextSize), + __0: (TextSize, ast::ParameterWithDefault, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action471( + __action474( mode, __0, __1, @@ -60876,23 +61067,23 @@ fn __action1336< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1337< +fn __action1344< >( mode: Mode, - __0: (TextSize, ast::ArgWithDefault, TextSize), + __0: (TextSize, ast::ParameterWithDefault, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action460( + __action463( mode, __0, __1, @@ -60903,27 +61094,27 @@ fn __action1337< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1338< +fn __action1345< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action979( + __action981( mode, __0, __1, @@ -60938,26 +61129,26 @@ fn __action1338< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1339< +fn __action1346< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action980( + __action982( mode, __0, __1, @@ -60971,28 +61162,28 @@ fn __action1339< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1340< +fn __action1347< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __7.2; let __end0 = __7.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action981( + __action983( mode, __0, __1, @@ -61008,27 +61199,27 @@ fn __action1340< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1341< +fn __action1348< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action982( + __action984( mode, __0, __1, @@ -61043,25 +61234,25 @@ fn __action1341< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1342< +fn __action1349< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action983( + __action985( mode, __0, __1, @@ -61074,24 +61265,24 @@ fn __action1342< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1343< +fn __action1350< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action984( + __action986( mode, __0, __1, @@ -61103,26 +61294,26 @@ fn __action1343< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1344< +fn __action1351< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action985( + __action987( mode, __0, __1, @@ -61136,25 +61327,25 @@ fn __action1344< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1345< +fn __action1352< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action986( + __action988( mode, __0, __1, @@ -61167,22 +61358,22 @@ fn __action1345< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1346< +fn __action1353< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action987( + __action989( mode, __0, __1, @@ -61192,26 +61383,26 @@ fn __action1346< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1347< +fn __action1354< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action988( + __action990( mode, __0, __1, @@ -61225,25 +61416,25 @@ fn __action1347< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1348< +fn __action1355< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action989( + __action991( mode, __0, __1, @@ -61256,27 +61447,27 @@ fn __action1348< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1349< +fn __action1356< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action990( + __action992( mode, __0, __1, @@ -61291,26 +61482,26 @@ fn __action1349< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1350< +fn __action1357< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action991( + __action993( mode, __0, __1, @@ -61324,24 +61515,24 @@ fn __action1350< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1351< +fn __action1358< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action992( + __action994( mode, __0, __1, @@ -61353,23 +61544,23 @@ fn __action1351< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1352< +fn __action1359< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action993( + __action995( mode, __0, __1, @@ -61380,25 +61571,25 @@ fn __action1352< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1353< +fn __action1360< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action994( + __action996( mode, __0, __1, @@ -61411,24 +61602,24 @@ fn __action1353< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1354< +fn __action1361< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action995( + __action997( mode, __0, __1, @@ -61440,21 +61631,21 @@ fn __action1354< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1355< +fn __action1362< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), -) -> Result> + __0: (TextSize, (Vec, Vec), TextSize), +) -> Result> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action996( + __action998( mode, __0, __temp0, @@ -61463,24 +61654,24 @@ fn __action1355< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1356< +fn __action1363< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action860( + __action864( mode, __0, __1, @@ -61492,23 +61683,23 @@ fn __action1356< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1357< +fn __action1364< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action861( + __action865( mode, __0, __1, @@ -61519,25 +61710,25 @@ fn __action1357< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1358< +fn __action1365< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action955( + __action957( mode, __0, __1, @@ -61550,24 +61741,24 @@ fn __action1358< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1359< +fn __action1366< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action956( + __action958( mode, __0, __1, @@ -61579,26 +61770,26 @@ fn __action1359< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1360< +fn __action1367< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action957( + __action959( mode, __0, __1, @@ -61612,25 +61803,25 @@ fn __action1360< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1361< +fn __action1368< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action958( + __action960( mode, __0, __1, @@ -61643,23 +61834,23 @@ fn __action1361< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1362< +fn __action1369< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action959( + __action961( mode, __0, __1, @@ -61670,22 +61861,22 @@ fn __action1362< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1363< +fn __action1370< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action960( + __action962( mode, __0, __1, @@ -61695,24 +61886,24 @@ fn __action1363< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1364< +fn __action1371< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action961( + __action963( mode, __0, __1, @@ -61724,23 +61915,23 @@ fn __action1364< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1365< +fn __action1372< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action962( + __action964( mode, __0, __1, @@ -61751,24 +61942,24 @@ fn __action1365< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1366< +fn __action1373< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result> + __3: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action963( + __action965( mode, __0, __1, @@ -61780,23 +61971,23 @@ fn __action1366< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1367< +fn __action1374< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action964( + __action966( mode, __0, __1, @@ -61807,25 +61998,25 @@ fn __action1367< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1368< +fn __action1375< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action965( + __action967( mode, __0, __1, @@ -61838,24 +62029,24 @@ fn __action1368< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1369< +fn __action1376< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result> + __3: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action966( + __action968( mode, __0, __1, @@ -61867,22 +62058,22 @@ fn __action1369< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1370< +fn __action1377< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Result> + __1: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action967( + __action969( mode, __0, __1, @@ -61892,21 +62083,21 @@ fn __action1370< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1371< +fn __action1378< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action968( + __action970( mode, __0, __temp0, @@ -61915,23 +62106,23 @@ fn __action1371< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1372< +fn __action1379< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action969( + __action971( mode, __0, __1, @@ -61942,22 +62133,22 @@ fn __action1372< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1373< +fn __action1380< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __1: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action970( + __action972( mode, __0, __1, @@ -61967,22 +62158,22 @@ fn __action1373< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1374< +fn __action1381< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action864( + __action868( mode, __0, __1, @@ -61992,21 +62183,21 @@ fn __action1374< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1375< +fn __action1382< >( mode: Mode, - __0: (TextSize, Option>, TextSize), -) -> ast::Arguments + __0: (TextSize, Option>, TextSize), +) -> ast::Parameters { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action865( + __action869( mode, __0, __temp0, @@ -62015,27 +62206,27 @@ fn __action1375< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1376< +fn __action1383< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1039( + __action1041( mode, __0, __1, @@ -62050,26 +62241,26 @@ fn __action1376< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1377< +fn __action1384< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1040( + __action1042( mode, __0, __1, @@ -62083,28 +62274,28 @@ fn __action1377< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1378< +fn __action1385< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __7.2; let __end0 = __7.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1041( + __action1043( mode, __0, __1, @@ -62120,27 +62311,27 @@ fn __action1378< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1379< +fn __action1386< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1042( + __action1044( mode, __0, __1, @@ -62155,25 +62346,25 @@ fn __action1379< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1380< +fn __action1387< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1043( + __action1045( mode, __0, __1, @@ -62186,24 +62377,24 @@ fn __action1380< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1381< +fn __action1388< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1044( + __action1046( mode, __0, __1, @@ -62215,26 +62406,26 @@ fn __action1381< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1382< +fn __action1389< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1045( + __action1047( mode, __0, __1, @@ -62248,25 +62439,25 @@ fn __action1382< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1383< +fn __action1390< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1046( + __action1048( mode, __0, __1, @@ -62279,22 +62470,22 @@ fn __action1383< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1384< +fn __action1391< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1047( + __action1049( mode, __0, __1, @@ -62304,26 +62495,26 @@ fn __action1384< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1385< +fn __action1392< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1048( + __action1050( mode, __0, __1, @@ -62337,25 +62528,25 @@ fn __action1385< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1386< +fn __action1393< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1049( + __action1051( mode, __0, __1, @@ -62368,27 +62559,27 @@ fn __action1386< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1387< +fn __action1394< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1050( + __action1052( mode, __0, __1, @@ -62403,26 +62594,26 @@ fn __action1387< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1388< +fn __action1395< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1051( + __action1053( mode, __0, __1, @@ -62436,24 +62627,24 @@ fn __action1388< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1389< +fn __action1396< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1052( + __action1054( mode, __0, __1, @@ -62465,23 +62656,23 @@ fn __action1389< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1390< +fn __action1397< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1053( + __action1055( mode, __0, __1, @@ -62492,25 +62683,25 @@ fn __action1390< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1391< +fn __action1398< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1054( + __action1056( mode, __0, __1, @@ -62523,24 +62714,24 @@ fn __action1391< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1392< +fn __action1399< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1055( + __action1057( mode, __0, __1, @@ -62552,21 +62743,21 @@ fn __action1392< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1393< +fn __action1400< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), -) -> Result> + __0: (TextSize, (Vec, Vec), TextSize), +) -> Result> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1056( + __action1058( mode, __0, __temp0, @@ -62575,24 +62766,24 @@ fn __action1393< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1394< +fn __action1401< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action868( + __action872( mode, __0, __1, @@ -62604,23 +62795,23 @@ fn __action1394< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1395< +fn __action1402< >( mode: Mode, - __0: (TextSize, (Vec, Vec), TextSize), + __0: (TextSize, (Vec, Vec), TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action869( + __action873( mode, __0, __1, @@ -62631,25 +62822,25 @@ fn __action1395< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1396< +fn __action1403< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1015( + __action1017( mode, __0, __1, @@ -62662,24 +62853,24 @@ fn __action1396< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1397< +fn __action1404< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1016( + __action1018( mode, __0, __1, @@ -62691,26 +62882,26 @@ fn __action1397< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1398< +fn __action1405< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1017( + __action1019( mode, __0, __1, @@ -62724,25 +62915,25 @@ fn __action1398< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1399< +fn __action1406< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), + __3: (TextSize, Option>, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1018( + __action1020( mode, __0, __1, @@ -62755,23 +62946,23 @@ fn __action1399< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1400< +fn __action1407< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1019( + __action1021( mode, __0, __1, @@ -62782,22 +62973,22 @@ fn __action1400< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1401< +fn __action1408< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1020( + __action1022( mode, __0, __1, @@ -62807,24 +62998,24 @@ fn __action1401< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1402< +fn __action1409< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1021( + __action1023( mode, __0, __1, @@ -62836,23 +63027,23 @@ fn __action1402< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1403< +fn __action1410< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1022( + __action1024( mode, __0, __1, @@ -62863,24 +63054,24 @@ fn __action1403< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1404< +fn __action1411< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), + __1: (TextSize, ast::Parameter, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result> + __3: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1023( + __action1025( mode, __0, __1, @@ -62892,23 +63083,23 @@ fn __action1404< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1405< +fn __action1412< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1024( + __action1026( mode, __0, __1, @@ -62919,25 +63110,25 @@ fn __action1405< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1406< +fn __action1413< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1025( + __action1027( mode, __0, __1, @@ -62950,24 +63141,24 @@ fn __action1406< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1407< +fn __action1414< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, alloc::vec::Vec, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, Option>, TextSize), -) -> Result> + __3: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1026( + __action1028( mode, __0, __1, @@ -62979,22 +63170,22 @@ fn __action1407< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1408< +fn __action1415< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Result> + __1: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1027( + __action1029( mode, __0, __1, @@ -63004,21 +63195,21 @@ fn __action1408< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1409< +fn __action1416< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1028( + __action1030( mode, __0, __temp0, @@ -63027,23 +63218,23 @@ fn __action1409< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1410< +fn __action1417< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), - __2: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __1: (TextSize, ast::Parameter, TextSize), + __2: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1029( + __action1031( mode, __0, __1, @@ -63054,22 +63245,22 @@ fn __action1410< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1411< +fn __action1418< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __1: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1030( + __action1032( mode, __0, __1, @@ -63079,22 +63270,22 @@ fn __action1411< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1412< +fn __action1419< >( mode: Mode, - __0: (TextSize, Option>, TextSize), + __0: (TextSize, Option>, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> ast::Arguments +) -> ast::Parameters { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action872( + __action876( mode, __0, __1, @@ -63104,21 +63295,21 @@ fn __action1412< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1413< +fn __action1420< >( mode: Mode, - __0: (TextSize, Option>, TextSize), -) -> ast::Arguments + __0: (TextSize, Option>, TextSize), +) -> ast::Parameters { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action873( + __action877( mode, __0, __temp0, @@ -63127,23 +63318,23 @@ fn __action1413< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1414< +fn __action1421< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, core::option::Option, TextSize), + __1: (TextSize, core::option::Option, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action886( + __action890( mode, __0, __1, @@ -63154,7 +63345,7 @@ fn __action1414< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1415< +fn __action1422< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63162,13 +63353,13 @@ fn __action1415< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action887( + __action891( mode, __0, __temp0, @@ -63177,7 +63368,7 @@ fn __action1415< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1416< +fn __action1423< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -63186,13 +63377,13 @@ fn __action1416< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action888( + __action892( mode, __0, __1, @@ -63202,7 +63393,7 @@ fn __action1416< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1417< +fn __action1424< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -63211,13 +63402,13 @@ fn __action1417< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action889( + __action893( mode, __0, __1, @@ -63227,7 +63418,7 @@ fn __action1417< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1418< +fn __action1425< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -63235,13 +63426,13 @@ fn __action1418< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action890( + __action894( mode, __0, __temp0, @@ -63250,7 +63441,7 @@ fn __action1418< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1419< +fn __action1426< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63260,13 +63451,13 @@ fn __action1419< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action891( + __action895( mode, __0, __1, @@ -63277,7 +63468,7 @@ fn __action1419< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1420< +fn __action1427< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63287,13 +63478,13 @@ fn __action1420< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action892( + __action896( mode, __0, __1, @@ -63304,7 +63495,7 @@ fn __action1420< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1421< +fn __action1428< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63312,13 +63503,13 @@ fn __action1421< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action893( + __action897( mode, __0, __temp0, @@ -63327,7 +63518,7 @@ fn __action1421< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1422< +fn __action1429< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63338,13 +63529,13 @@ fn __action1422< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1124( + __action1128( mode, __0, __1, @@ -63356,7 +63547,7 @@ fn __action1422< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1423< +fn __action1430< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63365,13 +63556,13 @@ fn __action1423< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1125( + __action1129( mode, __0, __1, @@ -63381,7 +63572,7 @@ fn __action1423< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1424< +fn __action1431< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63391,13 +63582,13 @@ fn __action1424< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action895( + __action899( mode, __0, __1, @@ -63408,7 +63599,7 @@ fn __action1424< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1425< +fn __action1432< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63417,13 +63608,13 @@ fn __action1425< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action896( + __action900( mode, __0, __1, @@ -63433,7 +63624,7 @@ fn __action1425< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1426< +fn __action1433< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63444,13 +63635,13 @@ fn __action1426< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action897( + __action901( mode, __0, __1, @@ -63462,7 +63653,7 @@ fn __action1426< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1427< +fn __action1434< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63474,13 +63665,13 @@ fn __action1427< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action898( + __action902( mode, __0, __1, @@ -63493,7 +63684,7 @@ fn __action1427< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1428< +fn __action1435< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63504,13 +63695,13 @@ fn __action1428< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action899( + __action903( mode, __0, __1, @@ -63522,7 +63713,7 @@ fn __action1428< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1429< +fn __action1436< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63532,13 +63723,13 @@ fn __action1429< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action900( + __action904( mode, __0, __1, @@ -63549,7 +63740,7 @@ fn __action1429< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1430< +fn __action1437< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63559,13 +63750,13 @@ fn __action1430< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action901( + __action905( mode, __0, __1, @@ -63576,7 +63767,7 @@ fn __action1430< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1431< +fn __action1438< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63586,13 +63777,13 @@ fn __action1431< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action902( + __action906( mode, __0, __1, @@ -63603,7 +63794,7 @@ fn __action1431< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1432< +fn __action1439< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63616,13 +63807,13 @@ fn __action1432< { let __start0 = __5.2; let __end0 = __5.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action903( + __action907( mode, __0, __1, @@ -63636,7 +63827,7 @@ fn __action1432< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1433< +fn __action1440< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63648,13 +63839,13 @@ fn __action1433< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action904( + __action908( mode, __0, __1, @@ -63667,7 +63858,7 @@ fn __action1433< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1434< +fn __action1441< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63676,13 +63867,13 @@ fn __action1434< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action906( + __action910( mode, __0, __1, @@ -63692,7 +63883,7 @@ fn __action1434< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1435< +fn __action1442< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -63701,13 +63892,13 @@ fn __action1435< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action907( + __action911( mode, __0, __1, @@ -63717,23 +63908,23 @@ fn __action1435< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1436< +fn __action1443< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1091( + __action1093( mode, __0, __1, @@ -63744,21 +63935,21 @@ fn __action1436< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1437< +fn __action1444< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1092( + __action1094( mode, __0, __temp0, @@ -63767,21 +63958,21 @@ fn __action1437< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1438< +fn __action1445< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), -) -> ast::Arg +) -> ast::Parameter { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action909( + __action913( mode, __0, __temp0, @@ -63790,7 +63981,7 @@ fn __action1438< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1439< +fn __action1446< >( mode: Mode, __0: (TextSize, core::option::Option, TextSize), @@ -63801,13 +63992,13 @@ fn __action1439< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action910( + __action914( mode, __0, __1, @@ -63819,7 +64010,7 @@ fn __action1439< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1440< +fn __action1447< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63827,13 +64018,13 @@ fn __action1440< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action911( + __action915( mode, __0, __temp0, @@ -63842,7 +64033,7 @@ fn __action1440< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1441< +fn __action1448< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63851,13 +64042,13 @@ fn __action1441< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action912( + __action916( mode, __0, __1, @@ -63867,7 +64058,7 @@ fn __action1441< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1442< +fn __action1449< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -63876,13 +64067,13 @@ fn __action1442< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action913( + __action917( mode, __0, __1, @@ -63892,7 +64083,7 @@ fn __action1442< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1443< +fn __action1450< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -63900,13 +64091,13 @@ fn __action1443< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action914( + __action918( mode, __0, __temp0, @@ -63915,7 +64106,7 @@ fn __action1443< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1444< +fn __action1451< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63925,13 +64116,13 @@ fn __action1444< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action915( + __action919( mode, __0, __1, @@ -63942,7 +64133,7 @@ fn __action1444< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1445< +fn __action1452< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63952,13 +64143,13 @@ fn __action1445< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action916( + __action920( mode, __0, __1, @@ -63969,7 +64160,7 @@ fn __action1445< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1446< +fn __action1453< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -63981,13 +64172,13 @@ fn __action1446< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action917( + __action921( mode, __0, __1, @@ -64000,7 +64191,7 @@ fn __action1446< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1447< +fn __action1454< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64012,13 +64203,13 @@ fn __action1447< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action918( + __action922( mode, __0, __1, @@ -64031,7 +64222,7 @@ fn __action1447< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1448< +fn __action1455< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64040,13 +64231,13 @@ fn __action1448< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action919( + __action923( mode, __0, __1, @@ -64056,7 +64247,7 @@ fn __action1448< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1449< +fn __action1456< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64065,13 +64256,13 @@ fn __action1449< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1095( + __action1099( mode, __0, __1, @@ -64081,7 +64272,7 @@ fn __action1449< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1450< +fn __action1457< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64091,164 +64282,24 @@ fn __action1450< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action1096( - mode, - __0, - __1, - __2, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1451< ->( - mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Suite, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Suite, TextSize), - __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt -{ - let __start0 = __9.2; - let __end0 = __9.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action1115( - mode, - __0, - __1, - __2, - __3, - __4, - __5, - __6, - __7, - __8, - __9, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1452< ->( - mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Suite, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt -{ - let __start0 = __6.2; - let __end0 = __6.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action1116( - mode, - __0, - __1, - __2, - __3, - __4, - __5, - __6, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1453< ->( - mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Suite, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Suite, TextSize), -) -> ast::Stmt -{ - let __start0 = __6.2; - let __end0 = __6.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action1117( - mode, - __0, - __1, - __2, - __3, - __4, - __5, - __6, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1454< ->( - mode: Mode, - __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Suite, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> ast::Stmt -{ - let __start0 = __3.2; - let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1118( + __action1100( mode, __0, __1, __2, - __3, __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1455< +fn __action1458< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64265,7 +64316,7 @@ fn __action1455< { let __start0 = __9.2; let __end0 = __9.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, @@ -64289,7 +64340,7 @@ fn __action1455< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1456< +fn __action1459< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64303,7 +64354,7 @@ fn __action1456< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, @@ -64324,7 +64375,7 @@ fn __action1456< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1457< +fn __action1460< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64338,7 +64389,7 @@ fn __action1457< { let __start0 = __6.2; let __end0 = __6.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, @@ -64359,7 +64410,7 @@ fn __action1457< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1458< +fn __action1461< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64370,7 +64421,7 @@ fn __action1458< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, @@ -64388,7 +64439,147 @@ fn __action1458< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1459< +fn __action1462< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Suite, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), + __7: (TextSize, token::Tok, TextSize), + __8: (TextSize, token::Tok, TextSize), + __9: (TextSize, ast::Suite, TextSize), +) -> ast::Stmt +{ + let __start0 = __9.2; + let __end0 = __9.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1123( + mode, + __0, + __1, + __2, + __3, + __4, + __5, + __6, + __7, + __8, + __9, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1463< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Suite, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), +) -> ast::Stmt +{ + let __start0 = __6.2; + let __end0 = __6.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1124( + mode, + __0, + __1, + __2, + __3, + __4, + __5, + __6, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1464< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Suite, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), +) -> ast::Stmt +{ + let __start0 = __6.2; + let __end0 = __6.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1125( + mode, + __0, + __1, + __2, + __3, + __4, + __5, + __6, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1465< +>( + mode: Mode, + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Suite, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> ast::Stmt +{ + let __start0 = __3.2; + let __end0 = __3.2; + let __temp0 = __action394( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1126( + mode, + __0, + __1, + __2, + __3, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1466< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -64396,13 +64587,13 @@ fn __action1459< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action924( + __action928( mode, __0, __temp0, @@ -64411,25 +64602,25 @@ fn __action1459< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1460< +fn __action1467< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Expr, TextSize), - __2: (TextSize, core::option::Option>, TextSize), + __2: (TextSize, core::option::Option, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Expr, TextSize), ) -> ast::Stmt { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action925( + __action929( mode, __0, __1, @@ -64442,7 +64633,7 @@ fn __action1460< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1461< +fn __action1468< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -64452,13 +64643,13 @@ fn __action1461< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1086( + __action1088( mode, __0, __1, @@ -64469,7 +64660,7 @@ fn __action1461< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1462< +fn __action1469< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -64477,13 +64668,13 @@ fn __action1462< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1087( + __action1089( mode, __0, __temp0, @@ -64492,7 +64683,7 @@ fn __action1462< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1463< +fn __action1470< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64501,13 +64692,13 @@ fn __action1463< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action927( + __action931( mode, __0, __1, @@ -64517,7 +64708,7 @@ fn __action1463< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1464< +fn __action1471< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64526,13 +64717,13 @@ fn __action1464< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action928( + __action932( mode, __0, __1, @@ -64542,24 +64733,24 @@ fn __action1464< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1465< +fn __action1472< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, Vec, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action929( + __action933( mode, __0, __1, @@ -64571,23 +64762,23 @@ fn __action1465< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1466< +fn __action1473< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, Vec, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Vec +) -> ast::TypeParams { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action930( + __action934( mode, __0, __1, @@ -64598,23 +64789,23 @@ fn __action1466< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1467< +fn __action1474< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Expr, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1088( + __action1090( mode, __0, __1, @@ -64625,21 +64816,21 @@ fn __action1467< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1468< +fn __action1475< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1089( + __action1091( mode, __0, __temp0, @@ -64648,21 +64839,21 @@ fn __action1468< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1469< +fn __action1476< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), -) -> ast::ArgWithDefault +) -> ast::ParameterWithDefault { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action932( + __action936( mode, __0, __temp0, @@ -64671,7 +64862,7 @@ fn __action1469< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1470< +fn __action1477< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64679,13 +64870,13 @@ fn __action1470< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action933( + __action937( mode, __0, __temp0, @@ -64694,7 +64885,7 @@ fn __action1470< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1471< +fn __action1478< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64702,76 +64893,22 @@ fn __action1471< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action935( - mode, - __0, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1472< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Expr, TextSize), -) -> ast::WithItem -{ - let __start0 = __2.2; - let __end0 = __2.2; - let __temp0 = __action389( - mode, - &__start0, - &__end0, - ); - let __temp0 = (__start0, __temp0, __end0); - __action936( - mode, - __0, - __1, - __2, - __temp0, - ) -} - -#[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action1473< ->( - mode: Mode, - __0: (TextSize, ast::Expr, TextSize), - __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, ast::Expr, TextSize), -) -> ast::WithItem -{ - let __start0 = __2.2; - let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action937( + __action939( mode, __0, - __1, - __2, __temp0, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1474< +fn __action1479< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64779,13 +64916,13 @@ fn __action1474< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action938( + __action940( mode, __0, __temp0, @@ -64794,7 +64931,7 @@ fn __action1474< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1475< +fn __action1480< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64804,13 +64941,13 @@ fn __action1475< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action939( + __action941( mode, __0, __1, @@ -64821,7 +64958,7 @@ fn __action1475< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1476< +fn __action1481< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -64829,13 +64966,13 @@ fn __action1476< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action940( + __action942( mode, __0, __temp0, @@ -64844,7 +64981,7 @@ fn __action1476< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1477< +fn __action1482< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64854,13 +64991,13 @@ fn __action1477< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action943( + __action945( mode, __0, __1, @@ -64871,7 +65008,7 @@ fn __action1477< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1478< +fn __action1483< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -64881,13 +65018,13 @@ fn __action1478< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action944( + __action946( mode, __0, __1, @@ -64898,7 +65035,7 @@ fn __action1478< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1479< +fn __action1484< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64907,13 +65044,13 @@ fn __action1479< { let __start0 = __1.2; let __end0 = __1.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action945( + __action947( mode, __0, __1, @@ -64923,7 +65060,7 @@ fn __action1479< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1480< +fn __action1485< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64933,13 +65070,13 @@ fn __action1480< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action389( + let __temp0 = __action394( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action946( + __action948( mode, __0, __1, @@ -64950,7 +65087,7 @@ fn __action1480< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1481< +fn __action1486< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -64959,7 +65096,7 @@ fn __action1481< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1476( + let __temp0 = __action1481( mode, __0, ); @@ -64973,7 +65110,7 @@ fn __action1481< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1482< +fn __action1487< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -64984,12 +65121,12 @@ fn __action1482< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1476( + let __temp0 = __action1481( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action644( + __action649( mode, __0, __temp0, @@ -65000,7 +65137,7 @@ fn __action1482< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1483< +fn __action1488< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65010,12 +65147,12 @@ fn __action1483< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1476( + let __temp0 = __action1481( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action645( + __action650( mode, __0, __temp0, @@ -65025,7 +65162,7 @@ fn __action1483< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1484< +fn __action1489< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -65034,7 +65171,7 @@ fn __action1484< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action1481( + let __temp0 = __action1486( mode, __0, __1, @@ -65048,7 +65185,7 @@ fn __action1484< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1485< +fn __action1490< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65061,13 +65198,13 @@ fn __action1485< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1484( + let __temp0 = __action1489( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1072( + __action1074( mode, __0, __temp0, @@ -65079,7 +65216,7 @@ fn __action1485< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1486< +fn __action1491< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65096,7 +65233,7 @@ fn __action1486< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1072( + __action1074( mode, __0, __temp0, @@ -65108,7 +65245,7 @@ fn __action1486< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1487< +fn __action1492< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65122,13 +65259,13 @@ fn __action1487< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1484( + let __temp0 = __action1489( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1073( + __action1075( mode, __0, __temp0, @@ -65141,7 +65278,7 @@ fn __action1487< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1488< +fn __action1493< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65159,7 +65296,7 @@ fn __action1488< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1073( + __action1075( mode, __0, __temp0, @@ -65172,7 +65309,7 @@ fn __action1488< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1489< +fn __action1494< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65184,13 +65321,13 @@ fn __action1489< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1484( + let __temp0 = __action1489( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1074( + __action1076( mode, __0, __temp0, @@ -65201,7 +65338,7 @@ fn __action1489< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1490< +fn __action1495< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65217,7 +65354,7 @@ fn __action1490< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1074( + __action1076( mode, __0, __temp0, @@ -65228,7 +65365,7 @@ fn __action1490< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1491< +fn __action1496< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65241,13 +65378,13 @@ fn __action1491< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1484( + let __temp0 = __action1489( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1075( + __action1077( mode, __0, __temp0, @@ -65259,7 +65396,7 @@ fn __action1491< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1492< +fn __action1497< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65276,7 +65413,7 @@ fn __action1492< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1075( + __action1077( mode, __0, __temp0, @@ -65288,7 +65425,7 @@ fn __action1492< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1493< +fn __action1498< >( mode: Mode, __0: (TextSize, (String, StringKind, bool), TextSize), @@ -65296,7 +65433,7 @@ fn __action1493< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1184( + let __temp0 = __action1188( mode, __0, ); @@ -65309,7 +65446,7 @@ fn __action1493< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1494< +fn __action1499< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(TextSize, (String, StringKind, bool), TextSize)>, TextSize), @@ -65318,7 +65455,7 @@ fn __action1494< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1184( + let __temp0 = __action1188( mode, __1, ); @@ -65332,7 +65469,7 @@ fn __action1494< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1495< +fn __action1500< >( mode: Mode, __0: (TextSize, ast::CmpOp, TextSize), @@ -65341,13 +65478,13 @@ fn __action1495< { let __start0 = __0.0; let __end0 = __1.2; - let __temp0 = __action490( + let __temp0 = __action495( mode, __0, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action488( + __action493( mode, __temp0, ) @@ -65355,7 +65492,7 @@ fn __action1495< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1496< +fn __action1501< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(ast::CmpOp, ast::Expr)>, TextSize), @@ -65365,13 +65502,13 @@ fn __action1496< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action490( + let __temp0 = __action495( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action489( + __action494( mode, __0, __temp0, @@ -65380,7 +65517,7 @@ fn __action1496< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1497< +fn __action1502< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -65401,7 +65538,7 @@ fn __action1497< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1498< +fn __action1503< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65413,12 +65550,12 @@ fn __action1498< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action1497( + let __temp0 = __action1502( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action843( + __action846( mode, __0, __1, @@ -65430,7 +65567,7 @@ fn __action1498< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1499< +fn __action1504< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65447,7 +65584,7 @@ fn __action1499< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action843( + __action846( mode, __0, __1, @@ -65459,20 +65596,20 @@ fn __action1499< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1500< +fn __action1505< >( mode: Mode, - __0: (TextSize, ast::Arguments, TextSize), -) -> core::option::Option + __0: (TextSize, ast::Parameters, TextSize), +) -> core::option::Option { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action277( + let __temp0 = __action278( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action275( + __action276( mode, __temp0, ) @@ -65480,22 +65617,22 @@ fn __action1500< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1501< +fn __action1506< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arguments, TextSize), + __1: (TextSize, ast::Parameters, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1500( + let __temp0 = __action1505( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1414( + __action1421( mode, __0, __temp0, @@ -65505,22 +65642,22 @@ fn __action1501< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1502< +fn __action1507< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action276( + let __temp0 = __action277( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1414( + __action1421( mode, __0, __temp0, @@ -65530,7 +65667,73 @@ fn __action1502< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1503< +fn __action1508< +>( + mode: Mode, + __0: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Identifier, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Arguments, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), +) -> ast::Stmt +{ + let __start0 = __4.0; + let __end0 = __4.2; + let __temp0 = __action268( + mode, + __4, + ); + let __temp0 = (__start0, __temp0, __end0); + __action763( + mode, + __0, + __1, + __2, + __3, + __temp0, + __5, + __6, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1509< +>( + mode: Mode, + __0: (TextSize, alloc::vec::Vec, TextSize), + __1: (TextSize, token::Tok, TextSize), + __2: (TextSize, ast::Identifier, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, ast::Suite, TextSize), +) -> ast::Stmt +{ + let __start0 = __3.2; + let __end0 = __4.0; + let __temp0 = __action269( + mode, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action763( + mode, + __0, + __1, + __2, + __3, + __temp0, + __4, + __5, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments)] +fn __action1510< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -65538,13 +65741,13 @@ fn __action1503< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action379( + let __temp0 = __action384( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1278( + __action1283( mode, __0, __temp0, @@ -65553,7 +65756,7 @@ fn __action1503< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1504< +fn __action1511< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -65562,12 +65765,12 @@ fn __action1504< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action380( + let __temp0 = __action385( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1278( + __action1283( mode, __0, __temp0, @@ -65576,7 +65779,7 @@ fn __action1504< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1505< +fn __action1512< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -65587,12 +65790,12 @@ fn __action1505< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action374( + let __temp0 = __action379( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1280( + __action1285( mode, __0, __1, @@ -65603,7 +65806,7 @@ fn __action1505< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1506< +fn __action1513< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -65613,13 +65816,13 @@ fn __action1506< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action375( + let __temp0 = __action380( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1280( + __action1285( mode, __0, __1, @@ -65630,7 +65833,7 @@ fn __action1506< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1507< +fn __action1514< >( mode: Mode, __0: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), @@ -65638,12 +65841,12 @@ fn __action1507< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action438( + let __temp0 = __action443( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1139( + __action1143( mode, __temp0, ) @@ -65651,7 +65854,7 @@ fn __action1507< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1508< +fn __action1515< >( mode: Mode, __lookbehind: &TextSize, @@ -65660,13 +65863,13 @@ fn __action1508< { let __start0 = *__lookbehind; let __end0 = *__lookahead; - let __temp0 = __action439( + let __temp0 = __action444( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1139( + __action1143( mode, __temp0, ) @@ -65674,7 +65877,7 @@ fn __action1508< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1509< +fn __action1516< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -65683,12 +65886,12 @@ fn __action1509< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action438( + let __temp0 = __action443( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1140( + __action1144( mode, __0, __temp0, @@ -65697,7 +65900,7 @@ fn __action1509< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1510< +fn __action1517< >( mode: Mode, __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), @@ -65705,13 +65908,13 @@ fn __action1510< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action439( + let __temp0 = __action444( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1140( + __action1144( mode, __0, __temp0, @@ -65720,95 +65923,109 @@ fn __action1510< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1511< +fn __action1518< >( mode: Mode, - __0: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), -) -> Result> + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), + __2: (TextSize, token::Tok, TextSize), +) -> Result> { - let __start0 = __0.0; - let __end0 = __0.2; - let __temp0 = __action1507( + let __start0 = __1.0; + let __end0 = __1.2; + let __temp0 = __action1514( mode, - __0, + __1, ); let __temp0 = (__start0, __temp0, __end0); - __action226( + __action1194( mode, + __0, __temp0, + __2, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1512< +fn __action1519< >( mode: Mode, - __lookbehind: &TextSize, - __lookahead: &TextSize, -) -> Result> + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, token::Tok, TextSize), +) -> Result> { - let __start0 = *__lookbehind; - let __end0 = *__lookahead; - let __temp0 = __action1508( + let __start0 = __0.2; + let __end0 = __1.0; + let __temp0 = __action1515( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action226( + __action1194( mode, + __0, __temp0, + __1, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1513< +fn __action1520< >( mode: Mode, - __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), - __1: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), -) -> Result> + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), + __2: (TextSize, (Option<(TextSize, TextSize, Option)>, ast::Expr), TextSize), + __3: (TextSize, token::Tok, TextSize), +) -> Result> { - let __start0 = __0.0; - let __end0 = __1.2; - let __temp0 = __action1509( + let __start0 = __1.0; + let __end0 = __2.2; + let __temp0 = __action1516( mode, - __0, __1, + __2, ); let __temp0 = (__start0, __temp0, __end0); - __action226( + __action1194( mode, + __0, __temp0, + __3, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1514< +fn __action1521< >( mode: Mode, - __0: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), -) -> Result> + __0: (TextSize, token::Tok, TextSize), + __1: (TextSize, alloc::vec::Vec<(Option<(TextSize, TextSize, Option)>, ast::Expr)>, TextSize), + __2: (TextSize, token::Tok, TextSize), +) -> Result> { - let __start0 = __0.0; - let __end0 = __0.2; - let __temp0 = __action1510( + let __start0 = __1.0; + let __end0 = __1.2; + let __temp0 = __action1517( mode, - __0, + __1, ); let __temp0 = (__start0, __temp0, __end0); - __action226( + __action1194( mode, + __0, __temp0, + __2, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1515< +fn __action1522< >( mode: Mode, __0: (TextSize, ast::Pattern, TextSize), @@ -65816,12 +66033,12 @@ fn __action1515< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action400( + let __temp0 = __action407( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1162( + __action1166( mode, __temp0, ) @@ -65829,7 +66046,7 @@ fn __action1515< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1516< +fn __action1523< >( mode: Mode, __lookbehind: &TextSize, @@ -65838,13 +66055,13 @@ fn __action1516< { let __start0 = *__lookbehind; let __end0 = *__lookahead; - let __temp0 = __action401( + let __temp0 = __action408( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1162( + __action1166( mode, __temp0, ) @@ -65852,7 +66069,7 @@ fn __action1516< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1517< +fn __action1524< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -65861,12 +66078,12 @@ fn __action1517< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action400( + let __temp0 = __action407( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1163( + __action1167( mode, __0, __temp0, @@ -65875,7 +66092,7 @@ fn __action1517< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1518< +fn __action1525< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -65883,13 +66100,13 @@ fn __action1518< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action401( + let __temp0 = __action408( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1163( + __action1167( mode, __0, __temp0, @@ -65898,7 +66115,7 @@ fn __action1518< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1519< +fn __action1526< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65908,12 +66125,12 @@ fn __action1519< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1515( + let __temp0 = __action1522( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1429( + __action1436( mode, __0, __temp0, @@ -65923,7 +66140,7 @@ fn __action1519< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1520< +fn __action1527< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65932,13 +66149,13 @@ fn __action1520< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action1516( + let __temp0 = __action1523( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1429( + __action1436( mode, __0, __temp0, @@ -65948,7 +66165,7 @@ fn __action1520< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1521< +fn __action1528< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65959,13 +66176,13 @@ fn __action1521< { let __start0 = __1.0; let __end0 = __2.2; - let __temp0 = __action1517( + let __temp0 = __action1524( mode, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1429( + __action1436( mode, __0, __temp0, @@ -65975,7 +66192,7 @@ fn __action1521< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1522< +fn __action1529< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -65985,12 +66202,12 @@ fn __action1522< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1518( + let __temp0 = __action1525( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1429( + __action1436( mode, __0, __temp0, @@ -66000,7 +66217,7 @@ fn __action1522< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1523< +fn __action1530< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -66009,12 +66226,12 @@ fn __action1523< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action235( + let __temp0 = __action239( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1287( + __action1292( mode, __0, __temp0, @@ -66023,7 +66240,7 @@ fn __action1523< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1524< +fn __action1531< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -66031,13 +66248,13 @@ fn __action1524< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action236( + let __temp0 = __action240( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1287( + __action1292( mode, __0, __temp0, @@ -66046,7 +66263,7 @@ fn __action1524< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1525< +fn __action1532< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66058,13 +66275,13 @@ fn __action1525< { let __start0 = __4.2; let __end0 = __4.2; - let __temp0 = __action238( + let __temp0 = __action242( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1432( + __action1439( mode, __0, __1, @@ -66077,7 +66294,7 @@ fn __action1525< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1526< +fn __action1533< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66090,12 +66307,12 @@ fn __action1526< { let __start0 = __5.0; let __end0 = __5.2; - let __temp0 = __action239( + let __temp0 = __action243( mode, __5, ); let __temp0 = (__start0, __temp0, __end0); - __action1432( + __action1439( mode, __0, __1, @@ -66108,7 +66325,7 @@ fn __action1526< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1527< +fn __action1534< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66119,13 +66336,13 @@ fn __action1527< { let __start0 = __3.2; let __end0 = __3.2; - let __temp0 = __action238( + let __temp0 = __action242( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1433( + __action1440( mode, __0, __1, @@ -66137,7 +66354,7 @@ fn __action1527< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1528< +fn __action1535< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66149,12 +66366,12 @@ fn __action1528< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action239( + let __temp0 = __action243( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action1433( + __action1440( mode, __0, __1, @@ -66166,28 +66383,26 @@ fn __action1528< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1529< +fn __action1536< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, core::option::Option>, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, ArgumentList, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, ast::Suite, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action760( + __action1508( mode, __temp0, __0, @@ -66196,35 +66411,31 @@ fn __action1529< __3, __4, __5, - __6, - __7, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1530< +fn __action1537< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ArgumentList, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, ast::Suite, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Arguments, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action760( + __action1508( mode, __temp0, __1, @@ -66233,32 +66444,30 @@ fn __action1530< __4, __5, __6, - __7, - __8, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1531< +fn __action1538< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, core::option::Option>, TextSize), + __2: (TextSize, core::option::Option, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action761( + __action1509( mode, __temp0, __0, @@ -66271,25 +66480,25 @@ fn __action1531< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1532< +fn __action1539< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), + __3: (TextSize, core::option::Option, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action761( + __action1509( mode, __temp0, __1, @@ -66302,14 +66511,14 @@ fn __action1532< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1533< +fn __action1540< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -66318,13 +66527,13 @@ fn __action1533< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1077( + __action1079( mode, __temp0, __0, @@ -66341,15 +66550,15 @@ fn __action1533< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1534< +fn __action1541< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Expr, TextSize), __8: (TextSize, token::Tok, TextSize), @@ -66358,12 +66567,12 @@ fn __action1534< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1077( + __action1079( mode, __temp0, __1, @@ -66380,27 +66589,27 @@ fn __action1534< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1535< +fn __action1542< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1078( + __action1080( mode, __temp0, __0, @@ -66415,27 +66624,27 @@ fn __action1535< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1536< +fn __action1543< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, core::option::Option>, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, core::option::Option, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1078( + __action1080( mode, __temp0, __1, @@ -66450,13 +66659,13 @@ fn __action1536< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1537< +fn __action1544< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, core::option::Option>, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Expr, TextSize), __6: (TextSize, token::Tok, TextSize), @@ -66465,13 +66674,13 @@ fn __action1537< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1079( + __action1081( mode, __temp0, __0, @@ -66487,14 +66696,14 @@ fn __action1537< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1538< +fn __action1545< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -66503,12 +66712,12 @@ fn __action1538< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1079( + __action1081( mode, __temp0, __1, @@ -66524,26 +66733,26 @@ fn __action1538< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1539< +fn __action1546< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, core::option::Option>, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, core::option::Option, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action287( + let __temp0 = __action288( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1080( + __action1082( mode, __temp0, __0, @@ -66557,26 +66766,26 @@ fn __action1539< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1540< +fn __action1547< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, core::option::Option>, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, core::option::Option, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action288( + let __temp0 = __action289( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1080( + __action1082( mode, __temp0, __1, @@ -66590,7 +66799,7 @@ fn __action1540< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1541< +fn __action1548< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66600,12 +66809,12 @@ fn __action1541< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action540( + let __temp0 = __action543( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1212( + __action1217( mode, __0, __temp0, @@ -66615,7 +66824,7 @@ fn __action1541< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1542< +fn __action1549< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66624,13 +66833,13 @@ fn __action1542< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action541( + let __temp0 = __action544( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1212( + __action1217( mode, __0, __temp0, @@ -66640,7 +66849,7 @@ fn __action1542< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1543< +fn __action1550< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66650,12 +66859,12 @@ fn __action1543< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action540( + let __temp0 = __action543( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1235( + __action1240( mode, __0, __temp0, @@ -66665,7 +66874,7 @@ fn __action1543< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1544< +fn __action1551< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66674,13 +66883,13 @@ fn __action1544< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action541( + let __temp0 = __action544( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1235( + __action1240( mode, __0, __temp0, @@ -66690,21 +66899,21 @@ fn __action1544< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1545< +fn __action1552< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arg, TextSize), -) -> Option> + __1: (TextSize, ast::Parameter, TextSize), +) -> Option> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action474( + let __temp0 = __action477( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action412( + __action419( mode, __0, __temp0, @@ -66713,21 +66922,21 @@ fn __action1545< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1546< +fn __action1553< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), -) -> Option> +) -> Option> { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action475( + let __temp0 = __action478( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action412( + __action419( mode, __0, __temp0, @@ -66736,7 +66945,7 @@ fn __action1546< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1547< +fn __action1554< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -66746,14 +66955,14 @@ fn __action1547< { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1297( + let __temp0 = __action1302( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action366( + __action371( mode, __temp0, ) @@ -66761,7 +66970,7 @@ fn __action1547< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1548< +fn __action1555< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -66769,12 +66978,12 @@ fn __action1548< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1298( + let __temp0 = __action1303( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action366( + __action371( mode, __temp0, ) @@ -66782,7 +66991,7 @@ fn __action1548< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1549< +fn __action1556< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -66794,14 +67003,14 @@ fn __action1549< { let __start0 = __2.0; let __end0 = __4.2; - let __temp0 = __action1297( + let __temp0 = __action1302( mode, __2, __3, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action367( + __action372( mode, __0, __1, @@ -66811,7 +67020,7 @@ fn __action1549< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1550< +fn __action1557< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -66821,12 +67030,12 @@ fn __action1550< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action1298( + let __temp0 = __action1303( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action367( + __action372( mode, __0, __1, @@ -66836,7 +67045,7 @@ fn __action1550< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1551< +fn __action1558< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -66846,14 +67055,14 @@ fn __action1551< { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action1299( + let __temp0 = __action1304( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action359( + __action364( mode, __temp0, ) @@ -66861,7 +67070,7 @@ fn __action1551< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1552< +fn __action1559< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -66869,12 +67078,12 @@ fn __action1552< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1300( + let __temp0 = __action1305( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action359( + __action364( mode, __temp0, ) @@ -66882,7 +67091,7 @@ fn __action1552< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1553< +fn __action1560< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -66894,14 +67103,14 @@ fn __action1553< { let __start0 = __2.0; let __end0 = __4.2; - let __temp0 = __action1299( + let __temp0 = __action1304( mode, __2, __3, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action360( + __action365( mode, __0, __1, @@ -66911,7 +67120,7 @@ fn __action1553< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1554< +fn __action1561< >( mode: Mode, __0: (TextSize, Vec, TextSize), @@ -66921,12 +67130,12 @@ fn __action1554< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action1300( + let __temp0 = __action1305( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action360( + __action365( mode, __0, __1, @@ -66936,7 +67145,7 @@ fn __action1554< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1555< +fn __action1562< >( mode: Mode, __0: (TextSize, ast::Identifier, TextSize), @@ -66944,13 +67153,13 @@ fn __action1555< { let __start0 = __0.0; let __end0 = __0.0; - let __temp0 = __action364( + let __temp0 = __action369( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action61( + __action62( mode, __temp0, __0, @@ -66959,7 +67168,7 @@ fn __action1555< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1556< +fn __action1563< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -66968,12 +67177,12 @@ fn __action1556< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action365( + let __temp0 = __action370( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action61( + __action62( mode, __temp0, __1, @@ -66982,7 +67191,7 @@ fn __action1556< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1557< +fn __action1564< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -66992,12 +67201,12 @@ fn __action1557< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action548( + let __temp0 = __action551( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1197( + __action1202( mode, __0, __temp0, @@ -67007,7 +67216,7 @@ fn __action1557< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1558< +fn __action1565< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -67016,13 +67225,13 @@ fn __action1558< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action549( + let __temp0 = __action552( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1197( + __action1202( mode, __0, __temp0, @@ -67032,7 +67241,7 @@ fn __action1558< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1559< +fn __action1566< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -67042,12 +67251,12 @@ fn __action1559< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action548( + let __temp0 = __action551( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1222( + __action1227( mode, __0, __temp0, @@ -67057,7 +67266,7 @@ fn __action1559< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1560< +fn __action1567< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -67066,13 +67275,13 @@ fn __action1560< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action549( + let __temp0 = __action552( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1222( + __action1227( mode, __0, __temp0, @@ -67082,26 +67291,26 @@ fn __action1560< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1561< +fn __action1568< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1338( + __action1345( mode, __temp0, __1, @@ -67115,30 +67324,30 @@ fn __action1561< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1562< +fn __action1569< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1338( + __action1345( mode, __temp0, __3, @@ -67152,24 +67361,24 @@ fn __action1562< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1563< +fn __action1570< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67177,7 +67386,7 @@ fn __action1563< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1338( + __action1345( mode, __temp0, __4, @@ -67191,25 +67400,25 @@ fn __action1563< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1564< +fn __action1571< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1339( + __action1346( mode, __temp0, __1, @@ -67222,29 +67431,29 @@ fn __action1564< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1565< +fn __action1572< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1339( + __action1346( mode, __temp0, __3, @@ -67257,23 +67466,23 @@ fn __action1565< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1566< +fn __action1573< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67281,7 +67490,7 @@ fn __action1566< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1339( + __action1346( mode, __temp0, __4, @@ -67294,27 +67503,27 @@ fn __action1566< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1567< +fn __action1574< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1340( + __action1347( mode, __temp0, __1, @@ -67329,31 +67538,31 @@ fn __action1567< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1568< +fn __action1575< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1340( + __action1347( mode, __temp0, __3, @@ -67368,25 +67577,25 @@ fn __action1568< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1569< +fn __action1576< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, Option>, TextSize), + __9: (TextSize, Option>, TextSize), __10: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67394,7 +67603,7 @@ fn __action1569< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1340( + __action1347( mode, __temp0, __4, @@ -67409,26 +67618,26 @@ fn __action1569< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1570< +fn __action1577< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1341( + __action1348( mode, __temp0, __1, @@ -67442,30 +67651,30 @@ fn __action1570< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1571< +fn __action1578< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1341( + __action1348( mode, __temp0, __3, @@ -67479,24 +67688,24 @@ fn __action1571< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1572< +fn __action1579< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67504,7 +67713,7 @@ fn __action1572< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1341( + __action1348( mode, __temp0, __4, @@ -67518,24 +67727,24 @@ fn __action1572< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1573< +fn __action1580< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1342( + __action1349( mode, __temp0, __1, @@ -67547,28 +67756,28 @@ fn __action1573< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1574< +fn __action1581< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1342( + __action1349( mode, __temp0, __3, @@ -67580,22 +67789,22 @@ fn __action1574< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1575< +fn __action1582< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67603,7 +67812,7 @@ fn __action1575< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1342( + __action1349( mode, __temp0, __4, @@ -67615,23 +67824,23 @@ fn __action1575< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1576< +fn __action1583< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1343( + __action1350( mode, __temp0, __1, @@ -67642,27 +67851,27 @@ fn __action1576< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1577< +fn __action1584< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1343( + __action1350( mode, __temp0, __3, @@ -67673,21 +67882,21 @@ fn __action1577< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1578< +fn __action1585< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67695,7 +67904,7 @@ fn __action1578< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1343( + __action1350( mode, __temp0, __4, @@ -67706,25 +67915,25 @@ fn __action1578< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1579< +fn __action1586< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1344( + __action1351( mode, __temp0, __1, @@ -67737,29 +67946,29 @@ fn __action1579< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1580< +fn __action1587< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1344( + __action1351( mode, __temp0, __3, @@ -67772,23 +67981,23 @@ fn __action1580< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1581< +fn __action1588< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67796,7 +68005,7 @@ fn __action1581< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1344( + __action1351( mode, __temp0, __4, @@ -67809,24 +68018,24 @@ fn __action1581< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1582< +fn __action1589< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1345( + __action1352( mode, __temp0, __1, @@ -67838,28 +68047,28 @@ fn __action1582< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1583< +fn __action1590< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1345( + __action1352( mode, __temp0, __3, @@ -67871,22 +68080,22 @@ fn __action1583< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1584< +fn __action1591< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67894,7 +68103,7 @@ fn __action1584< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1345( + __action1352( mode, __temp0, __4, @@ -67906,21 +68115,21 @@ fn __action1584< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1585< +fn __action1592< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1346( + __action1353( mode, __temp0, __1, @@ -67929,25 +68138,25 @@ fn __action1585< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1586< +fn __action1593< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1346( + __action1353( mode, __temp0, __3, @@ -67956,19 +68165,19 @@ fn __action1586< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1587< +fn __action1594< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -67976,7 +68185,7 @@ fn __action1587< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1346( + __action1353( mode, __temp0, __4, @@ -67985,25 +68194,25 @@ fn __action1587< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1588< +fn __action1595< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1347( + __action1354( mode, __temp0, __1, @@ -68016,29 +68225,29 @@ fn __action1588< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1589< +fn __action1596< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1347( + __action1354( mode, __temp0, __3, @@ -68051,23 +68260,23 @@ fn __action1589< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1590< +fn __action1597< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68075,7 +68284,7 @@ fn __action1590< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1347( + __action1354( mode, __temp0, __4, @@ -68088,24 +68297,24 @@ fn __action1590< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1591< +fn __action1598< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1348( + __action1355( mode, __temp0, __1, @@ -68117,28 +68326,28 @@ fn __action1591< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1592< +fn __action1599< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1348( + __action1355( mode, __temp0, __3, @@ -68150,22 +68359,22 @@ fn __action1592< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1593< +fn __action1600< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68173,7 +68382,7 @@ fn __action1593< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1348( + __action1355( mode, __temp0, __4, @@ -68185,26 +68394,26 @@ fn __action1593< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1594< +fn __action1601< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1349( + __action1356( mode, __temp0, __1, @@ -68218,30 +68427,30 @@ fn __action1594< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1595< +fn __action1602< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1349( + __action1356( mode, __temp0, __3, @@ -68255,24 +68464,24 @@ fn __action1595< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1596< +fn __action1603< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, Option>, TextSize), -) -> Result> + __9: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68280,7 +68489,7 @@ fn __action1596< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1349( + __action1356( mode, __temp0, __4, @@ -68294,25 +68503,25 @@ fn __action1596< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1597< +fn __action1604< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1350( + __action1357( mode, __temp0, __1, @@ -68325,29 +68534,29 @@ fn __action1597< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1598< +fn __action1605< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1350( + __action1357( mode, __temp0, __3, @@ -68360,23 +68569,23 @@ fn __action1598< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1599< +fn __action1606< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68384,7 +68593,7 @@ fn __action1599< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1350( + __action1357( mode, __temp0, __4, @@ -68397,23 +68606,23 @@ fn __action1599< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1600< +fn __action1607< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1351( + __action1358( mode, __temp0, __1, @@ -68424,27 +68633,27 @@ fn __action1600< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1601< +fn __action1608< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), -) -> Result> + __5: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1351( + __action1358( mode, __temp0, __3, @@ -68455,21 +68664,21 @@ fn __action1601< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1602< +fn __action1609< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), -) -> Result> + __6: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68477,7 +68686,7 @@ fn __action1602< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1351( + __action1358( mode, __temp0, __4, @@ -68488,22 +68697,22 @@ fn __action1602< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1603< +fn __action1610< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1352( + __action1359( mode, __temp0, __1, @@ -68513,26 +68722,26 @@ fn __action1603< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1604< +fn __action1611< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1352( + __action1359( mode, __temp0, __3, @@ -68542,20 +68751,20 @@ fn __action1604< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1605< +fn __action1612< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68563,7 +68772,7 @@ fn __action1605< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1352( + __action1359( mode, __temp0, __4, @@ -68573,24 +68782,24 @@ fn __action1605< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1606< +fn __action1613< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1353( + __action1360( mode, __temp0, __1, @@ -68602,28 +68811,28 @@ fn __action1606< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1607< +fn __action1614< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1353( + __action1360( mode, __temp0, __3, @@ -68635,22 +68844,22 @@ fn __action1607< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1608< +fn __action1615< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68658,7 +68867,7 @@ fn __action1608< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1353( + __action1360( mode, __temp0, __4, @@ -68670,23 +68879,23 @@ fn __action1608< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1609< +fn __action1616< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1354( + __action1361( mode, __temp0, __1, @@ -68697,27 +68906,27 @@ fn __action1609< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1610< +fn __action1617< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __5: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1354( + __action1361( mode, __temp0, __3, @@ -68728,21 +68937,21 @@ fn __action1610< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1611< +fn __action1618< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __6: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68750,7 +68959,7 @@ fn __action1611< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1354( + __action1361( mode, __temp0, __4, @@ -68761,20 +68970,20 @@ fn __action1611< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1612< +fn __action1619< >( mode: Mode, - __0: (TextSize, Vec, TextSize), -) -> Result> + __0: (TextSize, Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1355( + __action1362( mode, __temp0, ) @@ -68782,24 +68991,24 @@ fn __action1612< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1613< +fn __action1620< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1355( + __action1362( mode, __temp0, ) @@ -68807,18 +69016,18 @@ fn __action1613< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1614< +fn __action1621< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68826,7 +69035,7 @@ fn __action1614< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1355( + __action1362( mode, __temp0, ) @@ -68834,23 +69043,23 @@ fn __action1614< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1615< +fn __action1622< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1356( + __action1363( mode, __temp0, __1, @@ -68861,27 +69070,27 @@ fn __action1615< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1616< +fn __action1623< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1356( + __action1363( mode, __temp0, __3, @@ -68892,21 +69101,21 @@ fn __action1616< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1617< +fn __action1624< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -68914,7 +69123,7 @@ fn __action1617< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1356( + __action1363( mode, __temp0, __4, @@ -68925,22 +69134,22 @@ fn __action1617< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1618< +fn __action1625< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action417( + let __temp0 = __action424( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1357( + __action1364( mode, __temp0, __1, @@ -68950,26 +69159,26 @@ fn __action1618< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1619< +fn __action1626< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action679( + let __temp0 = __action681( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1357( + __action1364( mode, __temp0, __3, @@ -68979,20 +69188,20 @@ fn __action1619< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1620< +fn __action1627< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action680( + let __temp0 = __action682( mode, __0, __1, @@ -69000,7 +69209,7 @@ fn __action1620< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1357( + __action1364( mode, __temp0, __4, @@ -69010,26 +69219,26 @@ fn __action1620< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1621< +fn __action1628< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1376( + __action1383( mode, __temp0, __1, @@ -69043,30 +69252,30 @@ fn __action1621< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1622< +fn __action1629< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1376( + __action1383( mode, __temp0, __3, @@ -69080,24 +69289,24 @@ fn __action1622< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1623< +fn __action1630< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69105,7 +69314,7 @@ fn __action1623< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1376( + __action1383( mode, __temp0, __4, @@ -69119,25 +69328,25 @@ fn __action1623< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1624< +fn __action1631< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1377( + __action1384( mode, __temp0, __1, @@ -69150,29 +69359,29 @@ fn __action1624< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1625< +fn __action1632< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1377( + __action1384( mode, __temp0, __3, @@ -69185,23 +69394,23 @@ fn __action1625< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1626< +fn __action1633< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69209,7 +69418,7 @@ fn __action1626< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1377( + __action1384( mode, __temp0, __4, @@ -69222,27 +69431,27 @@ fn __action1626< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1627< +fn __action1634< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), + __6: (TextSize, Option>, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1378( + __action1385( mode, __temp0, __1, @@ -69257,31 +69466,31 @@ fn __action1627< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1628< +fn __action1635< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1378( + __action1385( mode, __temp0, __3, @@ -69296,25 +69505,25 @@ fn __action1628< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1629< +fn __action1636< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, Option>, TextSize), + __9: (TextSize, Option>, TextSize), __10: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69322,7 +69531,7 @@ fn __action1629< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1378( + __action1385( mode, __temp0, __4, @@ -69337,26 +69546,26 @@ fn __action1629< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1630< +fn __action1637< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1379( + __action1386( mode, __temp0, __1, @@ -69370,30 +69579,30 @@ fn __action1630< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1631< +fn __action1638< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), + __7: (TextSize, Option>, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1379( + __action1386( mode, __temp0, __3, @@ -69407,24 +69616,24 @@ fn __action1631< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1632< +fn __action1639< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), + __8: (TextSize, Option>, TextSize), __9: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69432,7 +69641,7 @@ fn __action1632< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1379( + __action1386( mode, __temp0, __4, @@ -69446,24 +69655,24 @@ fn __action1632< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1633< +fn __action1640< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1380( + __action1387( mode, __temp0, __1, @@ -69475,28 +69684,28 @@ fn __action1633< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1634< +fn __action1641< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1380( + __action1387( mode, __temp0, __3, @@ -69508,22 +69717,22 @@ fn __action1634< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1635< +fn __action1642< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69531,7 +69740,7 @@ fn __action1635< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1380( + __action1387( mode, __temp0, __4, @@ -69543,23 +69752,23 @@ fn __action1635< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1636< +fn __action1643< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1381( + __action1388( mode, __temp0, __1, @@ -69570,27 +69779,27 @@ fn __action1636< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1637< +fn __action1644< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1381( + __action1388( mode, __temp0, __3, @@ -69601,21 +69810,21 @@ fn __action1637< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1638< +fn __action1645< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69623,7 +69832,7 @@ fn __action1638< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1381( + __action1388( mode, __temp0, __4, @@ -69634,25 +69843,25 @@ fn __action1638< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1639< +fn __action1646< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1382( + __action1389( mode, __temp0, __1, @@ -69665,29 +69874,29 @@ fn __action1639< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1640< +fn __action1647< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1382( + __action1389( mode, __temp0, __3, @@ -69700,23 +69909,23 @@ fn __action1640< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1641< +fn __action1648< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69724,7 +69933,7 @@ fn __action1641< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1382( + __action1389( mode, __temp0, __4, @@ -69737,24 +69946,24 @@ fn __action1641< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1642< +fn __action1649< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1383( + __action1390( mode, __temp0, __1, @@ -69766,28 +69975,28 @@ fn __action1642< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1643< +fn __action1650< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1383( + __action1390( mode, __temp0, __3, @@ -69799,22 +70008,22 @@ fn __action1643< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1644< +fn __action1651< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69822,7 +70031,7 @@ fn __action1644< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1383( + __action1390( mode, __temp0, __4, @@ -69834,21 +70043,21 @@ fn __action1644< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1645< +fn __action1652< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1384( + __action1391( mode, __temp0, __1, @@ -69857,25 +70066,25 @@ fn __action1645< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1646< +fn __action1653< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1384( + __action1391( mode, __temp0, __3, @@ -69884,19 +70093,19 @@ fn __action1646< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1647< +fn __action1654< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -69904,7 +70113,7 @@ fn __action1647< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1384( + __action1391( mode, __temp0, __4, @@ -69913,25 +70122,25 @@ fn __action1647< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1648< +fn __action1655< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), + __3: (TextSize, ast::Parameter, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1385( + __action1392( mode, __temp0, __1, @@ -69944,29 +70153,29 @@ fn __action1648< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1649< +fn __action1656< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), + __5: (TextSize, ast::Parameter, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1385( + __action1392( mode, __temp0, __3, @@ -69979,23 +70188,23 @@ fn __action1649< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1650< +fn __action1657< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), + __6: (TextSize, ast::Parameter, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70003,7 +70212,7 @@ fn __action1650< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1385( + __action1392( mode, __temp0, __4, @@ -70016,24 +70225,24 @@ fn __action1650< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1651< +fn __action1658< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1386( + __action1393( mode, __temp0, __1, @@ -70045,28 +70254,28 @@ fn __action1651< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1652< +fn __action1659< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1386( + __action1393( mode, __temp0, __3, @@ -70078,22 +70287,22 @@ fn __action1652< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1653< +fn __action1660< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70101,7 +70310,7 @@ fn __action1653< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1386( + __action1393( mode, __temp0, __4, @@ -70113,26 +70322,26 @@ fn __action1653< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1654< +fn __action1661< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, Option>, TextSize), -) -> Result> + __6: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1387( + __action1394( mode, __temp0, __1, @@ -70146,30 +70355,30 @@ fn __action1654< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1655< +fn __action1662< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1387( + __action1394( mode, __temp0, __3, @@ -70183,24 +70392,24 @@ fn __action1655< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1656< +fn __action1663< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), __8: (TextSize, token::Tok, TextSize), - __9: (TextSize, Option>, TextSize), -) -> Result> + __9: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70208,7 +70417,7 @@ fn __action1656< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1387( + __action1394( mode, __temp0, __4, @@ -70222,25 +70431,25 @@ fn __action1656< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1657< +fn __action1664< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1388( + __action1395( mode, __temp0, __1, @@ -70253,29 +70462,29 @@ fn __action1657< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1658< +fn __action1665< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), + __5: (TextSize, alloc::vec::Vec, TextSize), __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, Option>, TextSize), -) -> Result> + __7: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1388( + __action1395( mode, __temp0, __3, @@ -70288,23 +70497,23 @@ fn __action1658< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1659< +fn __action1666< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, Option>, TextSize), -) -> Result> + __8: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70312,7 +70521,7 @@ fn __action1659< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1388( + __action1395( mode, __temp0, __4, @@ -70325,23 +70534,23 @@ fn __action1659< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1660< +fn __action1667< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1389( + __action1396( mode, __temp0, __1, @@ -70352,27 +70561,27 @@ fn __action1660< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1661< +fn __action1668< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), -) -> Result> + __5: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1389( + __action1396( mode, __temp0, __3, @@ -70383,21 +70592,21 @@ fn __action1661< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1662< +fn __action1669< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), -) -> Result> + __6: (TextSize, ast::Parameter, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70405,7 +70614,7 @@ fn __action1662< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1389( + __action1396( mode, __temp0, __4, @@ -70416,22 +70625,22 @@ fn __action1662< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1663< +fn __action1670< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1390( + __action1397( mode, __temp0, __1, @@ -70441,26 +70650,26 @@ fn __action1663< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1664< +fn __action1671< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1390( + __action1397( mode, __temp0, __3, @@ -70470,20 +70679,20 @@ fn __action1664< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1665< +fn __action1672< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70491,7 +70700,7 @@ fn __action1665< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1390( + __action1397( mode, __temp0, __4, @@ -70501,24 +70710,24 @@ fn __action1665< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1666< +fn __action1673< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ast::Arg, TextSize), - __4: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, ast::Parameter, TextSize), + __4: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1391( + __action1398( mode, __temp0, __1, @@ -70530,28 +70739,28 @@ fn __action1666< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1667< +fn __action1674< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ast::Arg, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __5: (TextSize, ast::Parameter, TextSize), + __6: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1391( + __action1398( mode, __temp0, __3, @@ -70563,22 +70772,22 @@ fn __action1667< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1668< +fn __action1675< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Arg, TextSize), - __7: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __6: (TextSize, ast::Parameter, TextSize), + __7: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70586,7 +70795,7 @@ fn __action1668< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1391( + __action1398( mode, __temp0, __4, @@ -70598,23 +70807,23 @@ fn __action1668< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1669< +fn __action1676< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1392( + __action1399( mode, __temp0, __1, @@ -70625,27 +70834,27 @@ fn __action1669< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1670< +fn __action1677< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __5: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1392( + __action1399( mode, __temp0, __3, @@ -70656,21 +70865,21 @@ fn __action1670< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1671< +fn __action1678< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __6: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70678,7 +70887,7 @@ fn __action1671< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1392( + __action1399( mode, __temp0, __4, @@ -70689,20 +70898,20 @@ fn __action1671< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1672< +fn __action1679< >( mode: Mode, - __0: (TextSize, Vec, TextSize), -) -> Result> + __0: (TextSize, Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1393( + __action1400( mode, __temp0, ) @@ -70710,24 +70919,24 @@ fn __action1672< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1673< +fn __action1680< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1393( + __action1400( mode, __temp0, ) @@ -70735,18 +70944,18 @@ fn __action1673< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1674< +fn __action1681< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), -) -> Result> + __3: (TextSize, alloc::vec::Vec, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70754,7 +70963,7 @@ fn __action1674< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1393( + __action1400( mode, __temp0, ) @@ -70762,23 +70971,23 @@ fn __action1674< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1675< +fn __action1682< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), + __2: (TextSize, Option>, TextSize), __3: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1394( + __action1401( mode, __temp0, __1, @@ -70789,27 +70998,27 @@ fn __action1675< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1676< +fn __action1683< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), + __4: (TextSize, Option>, TextSize), __5: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1394( + __action1401( mode, __temp0, __3, @@ -70820,21 +71029,21 @@ fn __action1676< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1677< +fn __action1684< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), + __5: (TextSize, Option>, TextSize), __6: (TextSize, token::Tok, TextSize), -) -> Result> +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70842,7 +71051,7 @@ fn __action1677< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1394( + __action1401( mode, __temp0, __4, @@ -70853,22 +71062,22 @@ fn __action1677< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1678< +fn __action1685< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), - __2: (TextSize, Option>, TextSize), -) -> Result> + __2: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action425( + let __temp0 = __action432( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1395( + __action1402( mode, __temp0, __1, @@ -70878,26 +71087,26 @@ fn __action1678< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1679< +fn __action1686< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, Option>, TextSize), -) -> Result> + __4: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __2.2; - let __temp0 = __action687( + let __temp0 = __action689( mode, __0, __1, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1395( + __action1402( mode, __temp0, __3, @@ -70907,20 +71116,20 @@ fn __action1679< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1680< +fn __action1687< >( mode: Mode, - __0: (TextSize, Vec, TextSize), + __0: (TextSize, Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, alloc::vec::Vec, TextSize), + __3: (TextSize, alloc::vec::Vec, TextSize), __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, Option>, TextSize), -) -> Result> + __5: (TextSize, Option>, TextSize), +) -> Result> { let __start0 = __0.0; let __end0 = __3.2; - let __temp0 = __action688( + let __temp0 = __action690( mode, __0, __1, @@ -70928,7 +71137,7 @@ fn __action1680< __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1395( + __action1402( mode, __temp0, __4, @@ -70938,23 +71147,23 @@ fn __action1680< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1681< +fn __action1688< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), - __1: (TextSize, ast::Arguments, TextSize), + __1: (TextSize, ast::Parameters, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Expr, TextSize), ) -> Result> { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action258( + let __temp0 = __action260( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1307( + __action1315( mode, __0, __temp0, @@ -70965,7 +71174,7 @@ fn __action1681< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1682< +fn __action1689< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -70975,13 +71184,13 @@ fn __action1682< { let __start0 = __0.2; let __end0 = __1.0; - let __temp0 = __action259( + let __temp0 = __action261( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1307( + __action1315( mode, __0, __temp0, @@ -70992,7 +71201,7 @@ fn __action1682< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1683< +fn __action1690< >( mode: Mode, __0: (TextSize, core::option::Option, TextSize), @@ -71003,12 +71212,12 @@ fn __action1683< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action254( + let __temp0 = __action256( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1439( + __action1446( mode, __0, __1, @@ -71019,7 +71228,7 @@ fn __action1683< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1684< +fn __action1691< >( mode: Mode, __0: (TextSize, core::option::Option, TextSize), @@ -71029,13 +71238,13 @@ fn __action1684< { let __start0 = __2.2; let __end0 = __2.2; - let __temp0 = __action255( + let __temp0 = __action257( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1439( + __action1446( mode, __0, __1, @@ -71046,7 +71255,7 @@ fn __action1684< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1685< +fn __action1692< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71062,7 +71271,7 @@ fn __action1685< __1, ); let __temp0 = (__start0, __temp0, __end0); - __action785( + __action787( mode, __0, __temp0, @@ -71073,7 +71282,7 @@ fn __action1685< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1686< +fn __action1693< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71089,7 +71298,7 @@ fn __action1686< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action785( + __action787( mode, __0, __temp0, @@ -71100,7 +71309,7 @@ fn __action1686< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1687< +fn __action1694< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71114,7 +71323,7 @@ fn __action1687< __1, ); let __temp0 = (__start0, __temp0, __end0); - __action905( + __action909( mode, __0, __temp0, @@ -71123,7 +71332,7 @@ fn __action1687< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1688< +fn __action1695< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71137,7 +71346,7 @@ fn __action1688< &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action905( + __action909( mode, __0, __temp0, @@ -71146,7 +71355,7 @@ fn __action1688< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1689< +fn __action1696< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71169,7 +71378,7 @@ fn __action1689< __2, ); let __temp1 = (__start1, __temp1, __end1); - __action1683( + __action1690( mode, __temp0, __1, @@ -71180,7 +71389,7 @@ fn __action1689< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1690< +fn __action1697< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71203,7 +71412,7 @@ fn __action1690< &__end1, ); let __temp1 = (__start1, __temp1, __end1); - __action1683( + __action1690( mode, __temp0, __1, @@ -71214,7 +71423,7 @@ fn __action1690< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1691< +fn __action1698< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71237,7 +71446,7 @@ fn __action1691< __1, ); let __temp1 = (__start1, __temp1, __end1); - __action1683( + __action1690( mode, __temp0, __0, @@ -71248,7 +71457,7 @@ fn __action1691< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1692< +fn __action1699< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71271,7 +71480,7 @@ fn __action1692< &__end1, ); let __temp1 = (__start1, __temp1, __end1); - __action1683( + __action1690( mode, __temp0, __0, @@ -71282,7 +71491,7 @@ fn __action1692< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1693< +fn __action1700< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71304,7 +71513,7 @@ fn __action1693< __2, ); let __temp1 = (__start1, __temp1, __end1); - __action1684( + __action1691( mode, __temp0, __1, @@ -71314,7 +71523,7 @@ fn __action1693< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1694< +fn __action1701< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71336,7 +71545,7 @@ fn __action1694< &__end1, ); let __temp1 = (__start1, __temp1, __end1); - __action1684( + __action1691( mode, __temp0, __1, @@ -71346,7 +71555,7 @@ fn __action1694< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1695< +fn __action1702< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71368,7 +71577,7 @@ fn __action1695< __1, ); let __temp1 = (__start1, __temp1, __end1); - __action1684( + __action1691( mode, __temp0, __0, @@ -71378,7 +71587,7 @@ fn __action1695< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1696< +fn __action1703< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71400,7 +71609,7 @@ fn __action1696< &__end1, ); let __temp1 = (__start1, __temp1, __end1); - __action1684( + __action1691( mode, __temp0, __0, @@ -71410,7 +71619,7 @@ fn __action1696< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1697< +fn __action1704< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71427,12 +71636,12 @@ fn __action1697< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action1103( + __action1107( mode, __0, __1, @@ -71449,7 +71658,7 @@ fn __action1697< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1698< +fn __action1705< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71463,12 +71672,12 @@ fn __action1698< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action1104( + __action1108( mode, __0, __1, @@ -71482,7 +71691,7 @@ fn __action1698< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1699< +fn __action1706< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71498,12 +71707,12 @@ fn __action1699< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1105( + __action1109( mode, __0, __1, @@ -71519,7 +71728,7 @@ fn __action1699< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1700< +fn __action1707< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71532,12 +71741,12 @@ fn __action1700< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1106( + __action1110( mode, __0, __1, @@ -71550,7 +71759,7 @@ fn __action1700< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1701< +fn __action1708< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71558,12 +71767,12 @@ fn __action1701< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action372( + __action377( mode, __temp0, ) @@ -71571,7 +71780,7 @@ fn __action1701< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1702< +fn __action1709< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71579,12 +71788,12 @@ fn __action1702< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action30( + __action31( mode, __temp0, ) @@ -71592,7 +71801,7 @@ fn __action1702< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1703< +fn __action1710< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71600,12 +71809,12 @@ fn __action1703< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action32( + __action33( mode, __temp0, ) @@ -71613,7 +71822,7 @@ fn __action1703< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1704< +fn __action1711< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71622,12 +71831,12 @@ fn __action1704< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1449( + __action1456( mode, __0, __temp0, @@ -71636,7 +71845,7 @@ fn __action1704< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1705< +fn __action1712< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71646,12 +71855,12 @@ fn __action1705< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action220( + let __temp0 = __action224( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1450( + __action1457( mode, __0, __temp0, @@ -71661,7 +71870,7 @@ fn __action1705< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1706< +fn __action1713< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71670,12 +71879,12 @@ fn __action1706< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1701( + let __temp0 = __action1708( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1285( + __action1290( mode, __0, __temp0, @@ -71684,7 +71893,7 @@ fn __action1706< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1707< +fn __action1714< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71692,13 +71901,13 @@ fn __action1707< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action373( + let __temp0 = __action378( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1285( + __action1290( mode, __0, __temp0, @@ -71707,7 +71916,7 @@ fn __action1707< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1708< +fn __action1715< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71716,12 +71925,12 @@ fn __action1708< { let __start0 = __1.0; let __end0 = __1.2; - let __temp0 = __action1701( + let __temp0 = __action1708( mode, __1, ); let __temp0 = (__start0, __temp0, __end0); - __action1479( + __action1484( mode, __0, __temp0, @@ -71730,7 +71939,7 @@ fn __action1708< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1709< +fn __action1716< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -71738,13 +71947,13 @@ fn __action1709< { let __start0 = __0.2; let __end0 = __0.2; - let __temp0 = __action373( + let __temp0 = __action378( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1479( + __action1484( mode, __0, __temp0, @@ -71753,7 +71962,7 @@ fn __action1709< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1710< +fn __action1717< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71761,12 +71970,12 @@ fn __action1710< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1703( + let __temp0 = __action1710( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1503( + __action1510( mode, __temp0, ) @@ -71774,7 +71983,7 @@ fn __action1710< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1711< +fn __action1718< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71783,12 +71992,12 @@ fn __action1711< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1703( + let __temp0 = __action1710( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1504( + __action1511( mode, __temp0, __1, @@ -71797,7 +72006,7 @@ fn __action1711< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1712< +fn __action1719< >( mode: Mode, __0: (TextSize, ast::Expr, TextSize), @@ -71807,12 +72016,12 @@ fn __action1712< { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action1703( + let __temp0 = __action1710( mode, __0, ); let __temp0 = (__start0, __temp0, __end0); - __action1279( + __action1284( mode, __temp0, __1, @@ -71822,27 +72031,25 @@ fn __action1712< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1713< +fn __action1720< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, Vec, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, ArgumentList, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, ast::Suite, TextSize), + __2: (TextSize, ast::TypeParams, TextSize), + __3: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1529( + __action1536( mode, __0, __1, @@ -71850,34 +72057,30 @@ fn __action1713< __3, __4, __5, - __6, - __7, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1714< +fn __action1721< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, token::Tok, TextSize), - __3: (TextSize, ArgumentList, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, ast::Suite, TextSize), + __2: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, token::Tok, TextSize), + __4: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1529( + __action1536( mode, __0, __1, @@ -71885,35 +72088,31 @@ fn __action1714< __2, __3, __4, - __5, - __6, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1715< +fn __action1722< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), - __4: (TextSize, token::Tok, TextSize), - __5: (TextSize, ArgumentList, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, token::Tok, TextSize), - __8: (TextSize, ast::Suite, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), + __4: (TextSize, ast::Arguments, TextSize), + __5: (TextSize, token::Tok, TextSize), + __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1530( + __action1537( mode, __0, __1, @@ -71922,35 +72121,31 @@ fn __action1715< __4, __5, __6, - __7, - __8, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1716< +fn __action1723< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, token::Tok, TextSize), - __4: (TextSize, ArgumentList, TextSize), - __5: (TextSize, token::Tok, TextSize), - __6: (TextSize, token::Tok, TextSize), - __7: (TextSize, ast::Suite, TextSize), + __3: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, token::Tok, TextSize), + __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1530( + __action1537( mode, __0, __1, @@ -71959,31 +72154,29 @@ fn __action1716< __3, __4, __5, - __6, - __7, ) } #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1717< +fn __action1724< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, Vec, TextSize), + __2: (TextSize, ast::TypeParams, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1531( + __action1538( mode, __0, __1, @@ -71995,7 +72188,7 @@ fn __action1717< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1718< +fn __action1725< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -72006,13 +72199,13 @@ fn __action1718< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1531( + __action1538( mode, __0, __1, @@ -72024,25 +72217,25 @@ fn __action1718< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1719< +fn __action1726< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1532( + __action1539( mode, __0, __1, @@ -72055,7 +72248,7 @@ fn __action1719< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1720< +fn __action1727< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), @@ -72067,13 +72260,13 @@ fn __action1720< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1532( + __action1539( mode, __0, __1, @@ -72086,14 +72279,14 @@ fn __action1720< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1721< +fn __action1728< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -72102,12 +72295,12 @@ fn __action1721< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1533( + __action1540( mode, __0, __1, @@ -72123,13 +72316,13 @@ fn __action1721< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1722< +fn __action1729< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Expr, TextSize), __6: (TextSize, token::Tok, TextSize), @@ -72138,13 +72331,13 @@ fn __action1722< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1533( + __action1540( mode, __0, __1, @@ -72160,15 +72353,15 @@ fn __action1722< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1723< +fn __action1730< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, Vec, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, ast::TypeParams, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Expr, TextSize), __8: (TextSize, token::Tok, TextSize), @@ -72177,12 +72370,12 @@ fn __action1723< { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action1534( + __action1541( mode, __0, __1, @@ -72199,14 +72392,14 @@ fn __action1723< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1724< +fn __action1731< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -72215,13 +72408,13 @@ fn __action1724< { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1534( + __action1541( mode, __0, __1, @@ -72238,26 +72431,26 @@ fn __action1724< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1725< +fn __action1732< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1535( + __action1542( mode, __0, __1, @@ -72271,26 +72464,26 @@ fn __action1725< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1726< +fn __action1733< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1535( + __action1542( mode, __0, __1, @@ -72304,27 +72497,27 @@ fn __action1726< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1727< +fn __action1734< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, Vec, TextSize), - __5: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, ast::TypeParams, TextSize), + __5: (TextSize, ast::Parameters, TextSize), __6: (TextSize, token::Tok, TextSize), __7: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __4.0; let __end0 = __4.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __4, ); let __temp0 = (__start0, __temp0, __end0); - __action1536( + __action1543( mode, __0, __1, @@ -72339,27 +72532,27 @@ fn __action1727< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1728< +fn __action1735< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, token::Tok, TextSize), __3: (TextSize, ast::Identifier, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __3.2; let __end0 = __4.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1536( + __action1543( mode, __0, __1, @@ -72374,13 +72567,13 @@ fn __action1728< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1729< +fn __action1736< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, Vec, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, ast::TypeParams, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Expr, TextSize), __6: (TextSize, token::Tok, TextSize), @@ -72389,12 +72582,12 @@ fn __action1729< { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1537( + __action1544( mode, __0, __1, @@ -72409,12 +72602,12 @@ fn __action1729< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1730< +fn __action1737< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, ast::Parameters, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Expr, TextSize), __5: (TextSize, token::Tok, TextSize), @@ -72423,13 +72616,13 @@ fn __action1730< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1537( + __action1544( mode, __0, __1, @@ -72444,14 +72637,14 @@ fn __action1730< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1731< +fn __action1738< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Expr, TextSize), __7: (TextSize, token::Tok, TextSize), @@ -72460,12 +72653,12 @@ fn __action1731< { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1538( + __action1545( mode, __0, __1, @@ -72481,13 +72674,13 @@ fn __action1731< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1732< +fn __action1739< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Expr, TextSize), __6: (TextSize, token::Tok, TextSize), @@ -72496,13 +72689,13 @@ fn __action1732< { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1538( + __action1545( mode, __0, __1, @@ -72518,25 +72711,25 @@ fn __action1732< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1733< +fn __action1740< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, Vec, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, ast::TypeParams, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1539( + __action1546( mode, __0, __1, @@ -72549,25 +72742,25 @@ fn __action1733< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1734< +fn __action1741< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Identifier, TextSize), - __2: (TextSize, ast::Arguments, TextSize), + __2: (TextSize, ast::Parameters, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1539( + __action1546( mode, __0, __1, @@ -72580,26 +72773,26 @@ fn __action1734< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1735< +fn __action1742< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, Vec, TextSize), - __4: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::TypeParams, TextSize), + __4: (TextSize, ast::Parameters, TextSize), __5: (TextSize, token::Tok, TextSize), __6: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __3.0; let __end0 = __3.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __3, ); let __temp0 = (__start0, __temp0, __end0); - __action1540( + __action1547( mode, __0, __1, @@ -72613,26 +72806,26 @@ fn __action1735< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1736< +fn __action1743< >( mode: Mode, __0: (TextSize, alloc::vec::Vec, TextSize), __1: (TextSize, token::Tok, TextSize), __2: (TextSize, ast::Identifier, TextSize), - __3: (TextSize, ast::Arguments, TextSize), + __3: (TextSize, ast::Parameters, TextSize), __4: (TextSize, token::Tok, TextSize), __5: (TextSize, ast::Suite, TextSize), ) -> ast::Stmt { let __start0 = __2.2; let __end0 = __3.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1540( + __action1547( mode, __0, __1, @@ -72646,24 +72839,24 @@ fn __action1736< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1737< +fn __action1744< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), __1: (TextSize, ast::Expr, TextSize), - __2: (TextSize, Vec, TextSize), + __2: (TextSize, ast::TypeParams, TextSize), __3: (TextSize, token::Tok, TextSize), __4: (TextSize, ast::Expr, TextSize), ) -> ast::Stmt { let __start0 = __2.0; let __end0 = __2.2; - let __temp0 = __action285( + let __temp0 = __action286( mode, __2, ); let __temp0 = (__start0, __temp0, __end0); - __action1460( + __action1467( mode, __0, __1, @@ -72675,7 +72868,7 @@ fn __action1737< #[allow(unused_variables)] #[allow(clippy::too_many_arguments)] -fn __action1738< +fn __action1745< >( mode: Mode, __0: (TextSize, token::Tok, TextSize), @@ -72686,13 +72879,13 @@ fn __action1738< { let __start0 = __1.2; let __end0 = __2.0; - let __temp0 = __action286( + let __temp0 = __action287( mode, &__start0, &__end0, ); let __temp0 = (__start0, __temp0, __end0); - __action1460( + __action1467( mode, __0, __1, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap index fb74fe3e48f29..2d4bf6ba9bc55 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap @@ -6,6 +6,7 @@ expression: parse_ast For( StmtFor { range: 0..24, + is_async: false, target: Name( ExprName { range: 4..5, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap index c77adbe5f3b1f..f977b375494de 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap @@ -6,6 +6,7 @@ expression: parse_ast With( StmtWith { range: 0..17, + is_async: false, items: [ WithItem { range: 5..11, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap index d862787c8a0f4..ad7dbadf9a774 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap @@ -7,21 +7,24 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..23, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..17, posonlyargs: [], args: [], vararg: None, kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "a", range: 9..10, }, @@ -29,11 +32,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "b", range: 12..13, }, @@ -41,11 +44,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 15..16, - def: Arg { + parameter: Parameter { range: 15..16, - arg: Identifier { + name: Identifier { id: "c", range: 15..16, }, @@ -56,6 +59,7 @@ Ok( ], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -63,9 +67,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap index f8eb841966b0a..33a05a02ec1e7 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap @@ -7,21 +7,24 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..29, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..23, posonlyargs: [], args: [], vararg: None, kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "a", range: 9..10, }, @@ -29,11 +32,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..16, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "b", range: 12..13, }, @@ -51,11 +54,11 @@ Ok( ), ), }, - ArgWithDefault { + ParameterWithDefault { range: 18..22, - def: Arg { + parameter: Parameter { range: 18..19, - arg: Identifier { + name: Identifier { id: "c", range: 18..19, }, @@ -76,6 +79,7 @@ Ok( ], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -83,9 +87,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap index 27a71b8f54405..4e2121628df29 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap @@ -7,11 +7,14 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..13, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..7, posonlyargs: [], args: [], @@ -19,6 +22,7 @@ Ok( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -26,9 +30,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap index 27a71b8f54405..4e2121628df29 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap @@ -7,11 +7,14 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..13, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..7, posonlyargs: [], args: [], @@ -19,6 +22,7 @@ Ok( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -26,9 +30,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap index 8ce96484b20bc..cd12db1311c6a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..32, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..26, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -54,11 +57,11 @@ Ok( ], vararg: None, kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 18..19, - def: Arg { + parameter: Parameter { range: 18..19, - arg: Identifier { + name: Identifier { id: "d", range: 18..19, }, @@ -66,11 +69,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 21..22, - def: Arg { + parameter: Parameter { range: 21..22, - arg: Identifier { + name: Identifier { id: "e", range: 21..22, }, @@ -78,11 +81,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 24..25, - def: Arg { + parameter: Parameter { range: 24..25, - arg: Identifier { + name: Identifier { id: "f", range: 24..25, }, @@ -93,6 +96,7 @@ Ok( ], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -100,9 +104,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap index d15f0ac3a9c8e..4276b8915b127 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..38, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..32, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -54,11 +57,11 @@ Ok( ], vararg: None, kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 18..19, - def: Arg { + parameter: Parameter { range: 18..19, - arg: Identifier { + name: Identifier { id: "d", range: 18..19, }, @@ -66,11 +69,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 21..25, - def: Arg { + parameter: Parameter { range: 21..22, - arg: Identifier { + name: Identifier { id: "e", range: 21..22, }, @@ -88,11 +91,11 @@ Ok( ), ), }, - ArgWithDefault { + ParameterWithDefault { range: 27..31, - def: Arg { + parameter: Parameter { range: 27..28, - arg: Identifier { + name: Identifier { id: "f", range: 27..28, }, @@ -113,6 +116,7 @@ Ok( ], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -120,9 +124,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap index d1aaae3e13dd1..ba1ece7a579a4 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..42, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..36, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -53,9 +56,9 @@ Ok( }, ], vararg: Some( - Arg { + Parameter { range: 16..20, - arg: Identifier { + name: Identifier { id: "args", range: 16..20, }, @@ -63,11 +66,11 @@ Ok( }, ), kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 22..23, - def: Arg { + parameter: Parameter { range: 22..23, - arg: Identifier { + name: Identifier { id: "d", range: 22..23, }, @@ -75,11 +78,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 25..29, - def: Arg { + parameter: Parameter { range: 25..26, - arg: Identifier { + name: Identifier { id: "e", range: 25..26, }, @@ -97,11 +100,11 @@ Ok( ), ), }, - ArgWithDefault { + ParameterWithDefault { range: 31..35, - def: Arg { + parameter: Parameter { range: 31..32, - arg: Identifier { + name: Identifier { id: "f", range: 31..32, }, @@ -122,6 +125,7 @@ Ok( ], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -129,9 +133,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap index 4169d01fa2b57..dc2888c7bdd3f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..52, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..46, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -53,9 +56,9 @@ Ok( }, ], vararg: Some( - Arg { + Parameter { range: 16..20, - arg: Identifier { + name: Identifier { id: "args", range: 16..20, }, @@ -63,11 +66,11 @@ Ok( }, ), kwonlyargs: [ - ArgWithDefault { + ParameterWithDefault { range: 22..23, - def: Arg { + parameter: Parameter { range: 22..23, - arg: Identifier { + name: Identifier { id: "d", range: 22..23, }, @@ -75,11 +78,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 25..29, - def: Arg { + parameter: Parameter { range: 25..26, - arg: Identifier { + name: Identifier { id: "e", range: 25..26, }, @@ -97,11 +100,11 @@ Ok( ), ), }, - ArgWithDefault { + ParameterWithDefault { range: 31..35, - def: Arg { + parameter: Parameter { range: 31..32, - arg: Identifier { + name: Identifier { id: "f", range: 31..32, }, @@ -121,9 +124,9 @@ Ok( }, ], kwarg: Some( - Arg { + Parameter { range: 39..45, - arg: Identifier { + name: Identifier { id: "kwargs", range: 39..45, }, @@ -131,6 +134,7 @@ Ok( }, ), }, + returns: None, body: [ Pass( StmtPass { @@ -138,9 +142,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap index b51a3a66c5ced..788b1b7a49066 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..20, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..14, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -56,6 +59,7 @@ Ok( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -63,9 +67,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap index 4ed3f2362b0b8..7c0459ab6c17a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..26, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..20, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..13, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -49,11 +52,11 @@ Ok( ), ), }, - ArgWithDefault { + ParameterWithDefault { range: 15..19, - def: Arg { + parameter: Parameter { range: 15..16, - arg: Identifier { + name: Identifier { id: "c", range: 15..16, }, @@ -76,6 +79,7 @@ Ok( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -83,9 +87,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap index b51a3a66c5ced..788b1b7a49066 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap @@ -7,19 +7,22 @@ Ok( FunctionDef( StmtFunctionDef { range: 0..20, + is_async: false, + decorator_list: [], name: Identifier { id: "f", range: 4..5, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 5..14, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 6..7, - def: Arg { + parameter: Parameter { range: 6..7, - arg: Identifier { + name: Identifier { id: "a", range: 6..7, }, @@ -27,11 +30,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "b", range: 9..10, }, @@ -39,11 +42,11 @@ Ok( }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 12..13, - def: Arg { + parameter: Parameter { range: 12..13, - arg: Identifier { + name: Identifier { id: "c", range: 12..13, }, @@ -56,6 +59,7 @@ Ok( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -63,9 +67,6 @@ Ok( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap index 174ed9b1b7a28..f5d230cfc2c54 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap @@ -10,51 +10,53 @@ Ok( value: Lambda( ExprLambda { range: 0..20, - args: Arguments { - range: 7..17, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [ - ArgWithDefault { - range: 10..11, - def: Arg { + parameters: Some( + Parameters { + range: 7..17, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [ + ParameterWithDefault { range: 10..11, - arg: Identifier { - id: "a", + parameter: Parameter { range: 10..11, + name: Identifier { + id: "a", + range: 10..11, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 13..14, - def: Arg { + ParameterWithDefault { range: 13..14, - arg: Identifier { - id: "b", + parameter: Parameter { range: 13..14, + name: Identifier { + id: "b", + range: 13..14, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 16..17, - def: Arg { + ParameterWithDefault { range: 16..17, - arg: Identifier { - id: "c", + parameter: Parameter { range: 16..17, + name: Identifier { + id: "c", + range: 16..17, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - kwarg: None, - }, + ], + kwarg: None, + }, + ), body: Constant( ExprConstant { range: 19..20, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap index 0b79a86f16667..838ab8abd4569 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap @@ -10,71 +10,73 @@ Ok( value: Lambda( ExprLambda { range: 0..26, - args: Arguments { - range: 7..23, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [ - ArgWithDefault { - range: 10..11, - def: Arg { + parameters: Some( + Parameters { + range: 7..23, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [ + ParameterWithDefault { range: 10..11, - arg: Identifier { - id: "a", + parameter: Parameter { range: 10..11, + name: Identifier { + id: "a", + range: 10..11, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 13..17, - def: Arg { - range: 13..14, - arg: Identifier { - id: "b", + ParameterWithDefault { + range: 13..17, + parameter: Parameter { range: 13..14, - }, - annotation: None, - }, - default: Some( - Constant( - ExprConstant { - range: 15..17, - value: Int( - 20, - ), - kind: None, + name: Identifier { + id: "b", + range: 13..14, }, - ), - ), - }, - ArgWithDefault { - range: 19..23, - def: Arg { - range: 19..20, - arg: Identifier { - id: "c", - range: 19..20, + annotation: None, }, - annotation: None, + default: Some( + Constant( + ExprConstant { + range: 15..17, + value: Int( + 20, + ), + kind: None, + }, + ), + ), }, - default: Some( - Constant( - ExprConstant { - range: 21..23, - value: Int( - 30, - ), - kind: None, + ParameterWithDefault { + range: 19..23, + parameter: Parameter { + range: 19..20, + name: Identifier { + id: "c", + range: 19..20, }, + annotation: None, + }, + default: Some( + Constant( + ExprConstant { + range: 21..23, + value: Int( + 30, + ), + kind: None, + }, + ), ), - ), - }, - ], - kwarg: None, - }, + }, + ], + kwarg: None, + }, + ), body: Constant( ExprConstant { range: 25..26, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap index 3562bea124355..4b90995b0062c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap @@ -10,14 +10,7 @@ Ok( value: Lambda( ExprLambda { range: 0..9, - args: Arguments { - range: 6..6, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + parameters: None, body: Constant( ExprConstant { range: 8..9, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap index 9240b4f472f86..a3eff7188b499 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap @@ -10,76 +10,78 @@ Ok( value: Lambda( ExprLambda { range: 0..26, - args: Arguments { - range: 7..23, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 7..8, - def: Arg { + parameters: Some( + Parameters { + range: 7..23, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 7..8, - arg: Identifier { - id: "a", + parameter: Parameter { range: 7..8, + name: Identifier { + id: "a", + range: 7..8, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 10..11, - def: Arg { + ParameterWithDefault { range: 10..11, - arg: Identifier { - id: "b", + parameter: Parameter { range: 10..11, + name: Identifier { + id: "b", + range: 10..11, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 13..14, - def: Arg { + ParameterWithDefault { range: 13..14, - arg: Identifier { - id: "c", + parameter: Parameter { range: 13..14, + name: Identifier { + id: "c", + range: 13..14, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [ - ArgWithDefault { - range: 19..20, - def: Arg { + ], + vararg: None, + kwonlyargs: [ + ParameterWithDefault { range: 19..20, - arg: Identifier { - id: "d", + parameter: Parameter { range: 19..20, + name: Identifier { + id: "d", + range: 19..20, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 22..23, - def: Arg { + ParameterWithDefault { range: 22..23, - arg: Identifier { - id: "e", + parameter: Parameter { range: 22..23, + name: Identifier { + id: "e", + range: 22..23, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - kwarg: None, - }, + ], + kwarg: None, + }, + ), body: Constant( ExprConstant { range: 25..26, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap index ba1c8ee2ebef7..1f8c1d0d3a751 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap @@ -10,51 +10,53 @@ Ok( value: Lambda( ExprLambda { range: 0..17, - args: Arguments { - range: 7..14, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 7..8, - def: Arg { + parameters: Some( + Parameters { + range: 7..14, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 7..8, - arg: Identifier { - id: "a", + parameter: Parameter { range: 7..8, + name: Identifier { + id: "a", + range: 7..8, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 10..11, - def: Arg { + ParameterWithDefault { range: 10..11, - arg: Identifier { - id: "b", + parameter: Parameter { range: 10..11, + name: Identifier { + id: "b", + range: 10..11, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 13..14, - def: Arg { + ParameterWithDefault { range: 13..14, - arg: Identifier { - id: "c", + parameter: Parameter { range: 13..14, + name: Identifier { + id: "c", + range: 13..14, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), body: Constant( ExprConstant { range: 16..17, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap index d3d028d5583bb..9760d71f28265 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap @@ -10,71 +10,73 @@ Ok( value: Lambda( ExprLambda { range: 0..23, - args: Arguments { - range: 7..20, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 7..8, - def: Arg { + parameters: Some( + Parameters { + range: 7..20, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 7..8, - arg: Identifier { - id: "a", + parameter: Parameter { range: 7..8, + name: Identifier { + id: "a", + range: 7..8, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 10..14, - def: Arg { - range: 10..11, - arg: Identifier { - id: "b", + ParameterWithDefault { + range: 10..14, + parameter: Parameter { range: 10..11, - }, - annotation: None, - }, - default: Some( - Constant( - ExprConstant { - range: 12..14, - value: Int( - 20, - ), - kind: None, + name: Identifier { + id: "b", + range: 10..11, }, - ), - ), - }, - ArgWithDefault { - range: 16..20, - def: Arg { - range: 16..17, - arg: Identifier { - id: "c", - range: 16..17, + annotation: None, }, - annotation: None, + default: Some( + Constant( + ExprConstant { + range: 12..14, + value: Int( + 20, + ), + kind: None, + }, + ), + ), }, - default: Some( - Constant( - ExprConstant { - range: 18..20, - value: Int( - 30, - ), - kind: None, + ParameterWithDefault { + range: 16..20, + parameter: Parameter { + range: 16..17, + name: Identifier { + id: "c", + range: 16..17, }, + annotation: None, + }, + default: Some( + Constant( + ExprConstant { + range: 18..20, + value: Int( + 30, + ), + kind: None, + }, + ), ), - ), - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), body: Constant( ExprConstant { range: 22..23, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__assignment.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__assignment.snap new file mode 100644 index 0000000000000..89978a14e8aef --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__assignment.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + Name { + name: "a_variable", + }, + Equal, + Int { + value: 99, + }, + Plus, + Int { + value: 2, + }, + Minus, + Int { + value: 0, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__empty_ipython_escape_command.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__empty_ipython_escape_command.snap new file mode 100644 index 0000000000000..a64dbdcce597b --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__empty_ipython_escape_command.snap @@ -0,0 +1,51 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_jupyter_source(source) +--- +[ + IpyEscapeCommand { + value: "", + kind: Magic, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Magic2, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Shell, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: ShCap, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Paren, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Quote, + }, + Newline, + IpyEscapeCommand { + value: "", + kind: Quote2, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command.snap new file mode 100644 index 0000000000000..2948f80190197 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command.snap @@ -0,0 +1,61 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_jupyter_source(source) +--- +[ + IpyEscapeCommand { + value: "foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "timeit a = b", + kind: Magic, + }, + Newline, + IpyEscapeCommand { + value: "timeit a % 3", + kind: Magic, + }, + Newline, + IpyEscapeCommand { + value: "matplotlib --inline", + kind: Magic, + }, + Newline, + IpyEscapeCommand { + value: "pwd && ls -a | sed 's/^/\\\\ /'", + kind: Shell, + }, + Newline, + IpyEscapeCommand { + value: "cd /Users/foo/Library/Application\\ Support/", + kind: ShCap, + }, + Newline, + IpyEscapeCommand { + value: "foo 1 2", + kind: Paren, + }, + Newline, + IpyEscapeCommand { + value: "foo 1 2", + kind: Quote, + }, + Newline, + IpyEscapeCommand { + value: "foo 1 2", + kind: Quote2, + }, + Newline, + IpyEscapeCommand { + value: "ls", + kind: Shell, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_assignment.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_assignment.snap new file mode 100644 index 0000000000000..8556594ddd4d1 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_assignment.snap @@ -0,0 +1,42 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_jupyter_source(source) +--- +[ + Name { + name: "pwd", + }, + Equal, + IpyEscapeCommand { + value: "pwd", + kind: Shell, + }, + Newline, + Name { + name: "foo", + }, + Equal, + IpyEscapeCommand { + value: "timeit a = b", + kind: Magic, + }, + Newline, + Name { + name: "bar", + }, + Equal, + IpyEscapeCommand { + value: "timeit a % 3", + kind: Magic, + }, + Newline, + Name { + name: "baz", + }, + Equal, + IpyEscapeCommand { + value: "matplotlib inline", + kind: Magic, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_indentation.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_indentation.snap new file mode 100644 index 0000000000000..a9dc876c1c531 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_escape_command_indentation.snap @@ -0,0 +1,17 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_jupyter_source(source) +--- +[ + If, + True, + Colon, + Newline, + Indent, + IpyEscapeCommand { + value: "matplotlib --inline", + kind: Magic, + }, + Newline, + Dedent, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_help_end_escape_command.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_help_end_escape_command.snap new file mode 100644 index 0000000000000..bcdfb44e19675 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__ipython_help_end_escape_command.snap @@ -0,0 +1,86 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_jupyter_source(source) +--- +[ + IpyEscapeCommand { + value: "foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: " foo ?", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo???", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "?foo???", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: " ?", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "??", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "%foo", + kind: Help, + }, + Newline, + IpyEscapeCommand { + value: "%foo", + kind: Help2, + }, + Newline, + IpyEscapeCommand { + value: "foo???", + kind: Magic2, + }, + Newline, + IpyEscapeCommand { + value: "pwd", + kind: Help, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__logical_newline_line_comment.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__logical_newline_line_comment.snap new file mode 100644 index 0000000000000..ac0200ef45e29 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__logical_newline_line_comment.snap @@ -0,0 +1,14 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + Comment( + "#Hello", + ), + NonLogicalNewline, + Comment( + "#World", + ), + NonLogicalNewline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__non_logical_newline_in_string_continuation.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__non_logical_newline_in_string_continuation.snap new file mode 100644 index 0000000000000..96203f7c24f0a --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__non_logical_newline_in_string_continuation.snap @@ -0,0 +1,34 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + Lpar, + NonLogicalNewline, + String { + value: "a", + kind: String, + triple_quoted: false, + }, + NonLogicalNewline, + String { + value: "b", + kind: String, + triple_quoted: false, + }, + NonLogicalNewline, + NonLogicalNewline, + String { + value: "c", + kind: String, + triple_quoted: false, + }, + String { + value: "d", + kind: String, + triple_quoted: false, + }, + NonLogicalNewline, + Rpar, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap new file mode 100644 index 0000000000000..272d88b186c6b --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap @@ -0,0 +1,42 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + Int { + value: 47, + }, + Int { + value: 10, + }, + Int { + value: 13, + }, + Int { + value: 0, + }, + Int { + value: 123, + }, + Int { + value: 1234567890, + }, + Float { + value: 0.2, + }, + Float { + value: 100.0, + }, + Float { + value: 2100.0, + }, + Complex { + real: 0.0, + imag: 2.0, + }, + Complex { + real: 0.0, + imag: 2.2, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__operators.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__operators.snap new file mode 100644 index 0000000000000..cc5b0e86f7cf8 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__operators.snap @@ -0,0 +1,12 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + DoubleSlash, + DoubleSlash, + DoubleSlashEqual, + Slash, + Slash, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__string.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__string.snap new file mode 100644 index 0000000000000..d4d89e878dd8c --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__string.snap @@ -0,0 +1,52 @@ +--- +source: crates/ruff_python_parser/src/lexer.rs +expression: lex_source(source) +--- +[ + String { + value: "double", + kind: String, + triple_quoted: false, + }, + String { + value: "single", + kind: String, + triple_quoted: false, + }, + String { + value: "can\\'t", + kind: String, + triple_quoted: false, + }, + String { + value: "\\\\\\\"", + kind: String, + triple_quoted: false, + }, + String { + value: "\\t\\r\\n", + kind: String, + triple_quoted: false, + }, + String { + value: "\\g", + kind: String, + triple_quoted: false, + }, + String { + value: "raw\\'", + kind: RawString, + triple_quoted: false, + }, + String { + value: "\\420", + kind: String, + triple_quoted: false, + }, + String { + value: "\\200\\0a", + kind: String, + triple_quoted: false, + }, + Newline, +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap index c32f7dcbcec92..160699606e8c5 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap @@ -6,11 +6,25 @@ expression: parse_ast FunctionDef( StmtFunctionDef { range: 0..34, + is_async: false, + decorator_list: [ + Decorator { + range: 0..13, + expression: Name( + ExprName { + range: 1..13, + id: "my_decorator", + ctx: Load, + }, + ), + }, + ], name: Identifier { id: "test", range: 18..22, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 22..24, posonlyargs: [], args: [], @@ -18,6 +32,7 @@ expression: parse_ast kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -25,31 +40,29 @@ expression: parse_ast }, ), ], + }, + ), + ClassDef( + StmtClassDef { + range: 36..73, decorator_list: [ Decorator { - range: 0..13, + range: 36..52, expression: Name( ExprName { - range: 1..13, - id: "my_decorator", + range: 37..52, + id: "class_decorator", ctx: Load, }, ), }, ], - returns: None, - type_params: [], - }, - ), - ClassDef( - StmtClassDef { - range: 36..73, name: Identifier { id: "Abcd", range: 59..63, }, - bases: [], - keywords: [], + type_params: None, + arguments: None, body: [ Pass( StmtPass { @@ -57,19 +70,6 @@ expression: parse_ast }, ), ], - type_params: [], - decorator_list: [ - Decorator { - range: 36..52, - expression: Name( - ExprName { - range: 37..52, - id: "class_decorator", - ctx: Load, - }, - ), - }, - ], }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap index 6d54f4db9e785..ff72ab9dafecc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap @@ -11,7 +11,10 @@ Dict( ExprConstant { range: 1..4, value: Str( - "a", + StringConstant { + value: "a", + implicit_concatenated: false, + }, ), kind: None, }, @@ -23,7 +26,10 @@ Dict( ExprConstant { range: 16..19, value: Str( - "d", + StringConstant { + value: "d", + implicit_concatenated: false, + }, ), kind: None, }, @@ -35,7 +41,10 @@ Dict( ExprConstant { range: 6..9, value: Str( - "b", + StringConstant { + value: "b", + implicit_concatenated: false, + }, ), kind: None, }, @@ -51,7 +60,10 @@ Dict( ExprConstant { range: 21..24, value: Str( - "e", + StringConstant { + value: "e", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap index c3883f47d9b8f..4617a2a863cd6 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap @@ -12,7 +12,10 @@ Call( ExprConstant { range: 0..3, value: Str( - " ", + StringConstant { + value: " ", + implicit_concatenated: false, + }, ), kind: None, }, @@ -24,124 +27,133 @@ Call( ctx: Load, }, ), - args: [ - GeneratorExp( - ExprGeneratorExp { - range: 14..139, - elt: Name( - ExprName { - range: 14..17, - id: "sql", - ctx: Load, - }, - ), - generators: [ - Comprehension { - range: 22..139, - target: Name( - ExprName { - range: 26..29, - id: "sql", - ctx: Store, - }, - ), - iter: Tuple( - ExprTuple { - range: 33..139, - elts: [ - IfExp( - ExprIfExp { - range: 43..80, - test: Name( - ExprName { - range: 65..70, - id: "limit", - ctx: Load, - }, - ), - body: BinOp( - ExprBinOp { - range: 43..61, - left: Constant( - ExprConstant { - range: 43..53, - value: Str( - "LIMIT %d", - ), - kind: None, - }, - ), - op: Mod, - right: Name( - ExprName { - range: 56..61, - id: "limit", - ctx: Load, - }, - ), - }, - ), - orelse: Constant( - ExprConstant { - range: 76..80, - value: None, - kind: None, - }, - ), - }, - ), - IfExp( - ExprIfExp { - range: 90..132, - test: Name( - ExprName { - range: 116..122, - id: "offset", - ctx: Load, - }, - ), - body: BinOp( - ExprBinOp { - range: 91..111, - left: Constant( - ExprConstant { - range: 91..102, - value: Str( - "OFFSET %d", - ), - kind: None, - }, - ), - op: Mod, - right: Name( - ExprName { - range: 105..111, - id: "offset", - ctx: Load, - }, - ), - }, - ), - orelse: Constant( - ExprConstant { - range: 128..132, - value: None, - kind: None, - }, - ), - }, - ), - ], - ctx: Load, - }, - ), - ifs: [], - is_async: false, - }, - ], - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 8..141, + args: [ + GeneratorExp( + ExprGeneratorExp { + range: 14..139, + elt: Name( + ExprName { + range: 14..17, + id: "sql", + ctx: Load, + }, + ), + generators: [ + Comprehension { + range: 22..139, + target: Name( + ExprName { + range: 26..29, + id: "sql", + ctx: Store, + }, + ), + iter: Tuple( + ExprTuple { + range: 33..139, + elts: [ + IfExp( + ExprIfExp { + range: 43..80, + test: Name( + ExprName { + range: 65..70, + id: "limit", + ctx: Load, + }, + ), + body: BinOp( + ExprBinOp { + range: 43..61, + left: Constant( + ExprConstant { + range: 43..53, + value: Str( + StringConstant { + value: "LIMIT %d", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + op: Mod, + right: Name( + ExprName { + range: 56..61, + id: "limit", + ctx: Load, + }, + ), + }, + ), + orelse: Constant( + ExprConstant { + range: 76..80, + value: None, + kind: None, + }, + ), + }, + ), + IfExp( + ExprIfExp { + range: 90..132, + test: Name( + ExprName { + range: 116..122, + id: "offset", + ctx: Load, + }, + ), + body: BinOp( + ExprBinOp { + range: 91..111, + left: Constant( + ExprConstant { + range: 91..102, + value: Str( + StringConstant { + value: "OFFSET %d", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + op: Mod, + right: Name( + ExprName { + range: 105..111, + id: "offset", + ctx: Load, + }, + ), + }, + ), + orelse: Constant( + ExprConstant { + range: 128..132, + value: None, + kind: None, + }, + ), + }, + ), + ], + ctx: Load, + }, + ), + ifs: [], + is_async: false, + }, + ], + }, + ), + ], + keywords: [], + }, }, ) diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__ipython_escape_commands.snap similarity index 64% rename from crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap rename to crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__ipython_escape_commands.snap index f24364d893931..3d06cd7aeb1ac 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__ipython_escape_commands.snap @@ -4,7 +4,7 @@ expression: parse_ast --- Module( ModModule { - range: 0..803, + range: 0..929, body: [ Expr( StmtExpr { @@ -31,92 +31,92 @@ Module( ), }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 66..73, kind: Help2, value: "a.foo", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 74..80, kind: Help, value: "a.foo", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 81..88, kind: Help, - value: "a.foo?", + value: "a.foo", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 89..100, kind: Help2, - value: "a.foo()??", + value: "a.foo()", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 115..128, kind: Magic, value: "timeit a = b", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 129..147, kind: Magic, value: "timeit foo(b) % 3", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 148..176, kind: Magic, value: "alias showPath pwd && ls -a", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 177..205, kind: Magic, value: "timeit a = foo(b); b = 2", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 206..226, kind: Magic, value: "matplotlib --inline", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 227..253, kind: Magic, value: "matplotlib --inline", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 277..309, kind: Shell, value: "pwd && ls -a | sed 's/^/\\ /'", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 310..347, kind: Shell, value: "pwd && ls -a | sed 's/^/\\\\ /'", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 348..393, kind: ShCap, value: "cd /Users/foo/Library/Application\\ Support/", @@ -125,11 +125,14 @@ Module( FunctionDef( StmtFunctionDef { range: 566..626, + is_async: false, + decorator_list: [], name: Identifier { id: "foo", range: 570..573, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 573..575, posonlyargs: [], args: [], @@ -137,6 +140,7 @@ Module( kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Return( StmtReturn { @@ -170,27 +174,24 @@ Module( }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 656..664, kind: Paren, value: "foo 1 2", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 665..673, kind: Quote2, value: "foo 1 2", }, ), - LineMagic( - StmtLineMagic { + IpyEscapeCommand( + StmtIpyEscapeCommand { range: 674..682, kind: Quote, value: "foo 1 2", @@ -198,42 +199,46 @@ Module( ), For( StmtFor { - range: 701..727, + range: 711..737, + is_async: false, target: Name( ExprName { - range: 705..706, + range: 715..716, id: "a", ctx: Store, }, ), iter: Call( ExprCall { - range: 710..718, + range: 720..728, func: Name( ExprName { - range: 710..715, + range: 720..725, id: "range", ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 716..717, - value: Int( - 5, - ), - kind: None, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 725..728, + args: [ + Constant( + ExprConstant { + range: 726..727, + value: Int( + 5, + ), + kind: None, + }, + ), + ], + keywords: [], + }, }, ), body: [ - LineMagic( - StmtLineMagic { - range: 724..727, + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 734..737, kind: Shell, value: "ls", }, @@ -244,19 +249,19 @@ Module( ), Assign( StmtAssign { - range: 729..738, + range: 739..748, targets: [ Name( ExprName { - range: 729..731, + range: 739..741, id: "p1", ctx: Store, }, ), ], - value: LineMagic( - ExprLineMagic { - range: 734..738, + value: IpyEscapeCommand( + ExprIpyEscapeCommand { + range: 744..748, kind: Shell, value: "pwd", }, @@ -265,25 +270,25 @@ Module( ), AnnAssign( StmtAnnAssign { - range: 739..753, + range: 749..763, target: Name( ExprName { - range: 739..741, + range: 749..751, id: "p2", ctx: Store, }, ), annotation: Name( ExprName { - range: 743..746, + range: 753..756, id: "str", ctx: Load, }, ), value: Some( - LineMagic( - ExprLineMagic { - range: 749..753, + IpyEscapeCommand( + ExprIpyEscapeCommand { + range: 759..763, kind: Shell, value: "pwd", }, @@ -294,53 +299,102 @@ Module( ), Assign( StmtAssign { - range: 754..774, + range: 764..784, targets: [ Name( ExprName { - range: 754..757, + range: 764..767, id: "foo", ctx: Store, }, ), ], - value: LineMagic( - ExprLineMagic { - range: 760..774, + value: IpyEscapeCommand( + ExprIpyEscapeCommand { + range: 770..784, kind: Magic, value: "foo bar", }, ), }, ), - LineMagic( - StmtLineMagic { - range: 776..781, + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 786..791, kind: Magic, value: " foo", }, ), Assign( StmtAssign { - range: 782..803, + range: 792..813, targets: [ Name( ExprName { - range: 782..785, + range: 792..795, id: "foo", ctx: Store, }, ), ], - value: LineMagic( - ExprLineMagic { - range: 788..803, + value: IpyEscapeCommand( + ExprIpyEscapeCommand { + range: 798..813, kind: Magic, value: "foo # comment", }, ), }, ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 838..842, + kind: Help, + value: "foo", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 843..852, + kind: Help2, + value: "foo.bar", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 853..865, + kind: Help, + value: "foo.bar.baz", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 866..874, + kind: Help2, + value: "foo[0]", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 875..885, + kind: Help, + value: "foo[0][1]", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 886..905, + kind: Help2, + value: "foo.bar[0].baz[1]", + }, + ), + IpyEscapeCommand( + StmtIpyEscapeCommand { + range: 906..929, + kind: Help2, + value: "foo.bar[0].baz[2].egg", + }, + ), ], }, ) diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap index cc1bb69d34f96..c862d1c1dae2a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap @@ -15,7 +15,10 @@ expression: parse_ast ExprConstant { range: 8..14, value: Str( - "test", + StringConstant { + value: "test", + implicit_concatenated: false, + }, ), kind: None, }, @@ -66,16 +69,19 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Name( - ExprName { - range: 68..72, - id: "rest", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 67..73, + args: [ + Name( + ExprName { + range: 68..72, + id: "rest", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -97,7 +103,10 @@ expression: parse_ast ExprConstant { range: 81..88, value: Str( - "label", + StringConstant { + value: "label", + implicit_concatenated: false, + }, ), kind: None, }, @@ -109,7 +118,10 @@ expression: parse_ast ExprConstant { range: 90..96, value: Str( - "test", + StringConstant { + value: "test", + implicit_concatenated: false, + }, ), kind: None, }, @@ -128,7 +140,10 @@ expression: parse_ast ExprConstant { range: 118..125, value: Str( - "label", + StringConstant { + value: "label", + implicit_concatenated: false, + }, ), kind: None, }, @@ -195,16 +210,19 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Name( - ExprName { - range: 171..176, - id: "label", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 170..177, + args: [ + Name( + ExprName { + range: 171..176, + id: "label", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap index 94b281807ceb4..38a83842e20ed 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap @@ -1,6 +1,6 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ Expr( @@ -122,42 +122,45 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Starred( - ExprStarred { - range: 93..99, - value: BinOp( - ExprBinOp { - range: 94..99, - left: Name( - ExprName { - range: 94..95, - id: "a", - ctx: Load, - }, - ), - op: Add, - right: Name( - ExprName { - range: 98..99, - id: "b", - ctx: Load, - }, - ), - }, - ), - ctx: Load, - }, - ), - Name( - ExprName { - range: 101..102, - id: "c", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 92..103, + args: [ + Starred( + ExprStarred { + range: 93..99, + value: BinOp( + ExprBinOp { + range: 94..99, + left: Name( + ExprName { + range: 94..95, + id: "a", + ctx: Load, + }, + ), + op: Add, + right: Name( + ExprName { + range: 98..99, + id: "b", + ctx: Load, + }, + ), + }, + ), + ctx: Load, + }, + ), + Name( + ExprName { + range: 101..102, + id: "c", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -283,22 +286,25 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - UnaryOp( - ExprUnaryOp { - range: 225..227, - op: USub, - operand: Name( - ExprName { - range: 226..227, - id: "a", - ctx: Load, - }, - ), - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 224..228, + args: [ + UnaryOp( + ExprUnaryOp { + range: 225..227, + op: USub, + operand: Name( + ExprName { + range: 226..227, + id: "a", + ctx: Load, + }, + ), + }, + ), + ], + keywords: [], + }, }, ), op: Mult, @@ -339,8 +345,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 270..272, + args: [], + keywords: [], + }, }, ), attr: Identifier { @@ -368,16 +377,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Tuple( - ExprTuple { - range: 298..300, - elts: [], - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 297..301, + args: [ + Tuple( + ExprTuple { + range: 298..300, + elts: [], + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), attr: Identifier { @@ -405,16 +417,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Tuple( - ExprTuple { - range: 329..331, - elts: [], - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 328..333, + args: [ + Tuple( + ExprTuple { + range: 329..331, + elts: [], + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), attr: Identifier { @@ -563,8 +578,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 476..478, + args: [], + keywords: [], + }, }, ), slice: Slice( @@ -709,27 +727,29 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" value: Lambda( ExprLambda { range: 591..619, - args: Arguments { - range: 598..603, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 598..603, - def: Arg { + parameters: Some( + Parameters { + range: 598..603, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 598..603, - arg: Identifier { - id: "query", + parameter: Parameter { range: 598..603, + name: Identifier { + id: "query", + range: 598..603, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), body: Compare( ExprCompare { range: 605..619, @@ -771,33 +791,39 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Call( - ExprCall { - range: 626..635, - func: Name( - ExprName { - range: 626..631, - id: "match", - ctx: Load, - }, - ), - args: [ - Constant( - ExprConstant { - range: 632..634, - value: Int( - 12, - ), - kind: None, + arguments: Arguments { + range: 625..636, + args: [ + Call( + ExprCall { + range: 626..635, + func: Name( + ExprName { + range: 626..631, + id: "match", + ctx: Load, }, ), - ], - keywords: [], - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 631..635, + args: [ + Constant( + ExprConstant { + range: 632..634, + value: Int( + 12, + ), + kind: None, + }, + ), + ], + keywords: [], + }, + }, + ), + ], + keywords: [], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__named_expression.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__named_expression.snap new file mode 100644 index 0000000000000..18aef224edf66 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__named_expression.snap @@ -0,0 +1,36 @@ +--- +source: crates/ruff_python_parser/src/parser.rs +expression: parse_ast +--- +NamedExpr( + ExprNamedExpr { + range: 1..15, + target: Name( + ExprName { + range: 1..2, + id: "x", + ctx: Store, + }, + ), + value: BinOp( + ExprBinOp { + range: 8..13, + left: Name( + ExprName { + range: 8..9, + id: "y", + ctx: Load, + }, + ), + op: Mult, + right: Name( + ExprName { + range: 12..13, + id: "z", + ctx: Load, + }, + ), + }, + ), + }, +) diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap index f554311a33374..5b5e4e8acf43e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap @@ -1,6 +1,6 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ Assign( @@ -37,8 +37,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 17..19, + args: [], + keywords: [], + }, }, ), }, @@ -176,8 +179,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 88..90, + args: [], + keywords: [], + }, }, ), }, @@ -249,8 +255,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 165..167, + args: [], + keywords: [], + }, }, ), }, @@ -324,35 +333,41 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Call( - ExprCall { - range: 221..240, - func: Attribute( - ExprAttribute { - range: 221..238, - value: Constant( - ExprConstant { - range: 221..227, - value: Int( - 11, - ), - kind: None, + arguments: Arguments { + range: 220..241, + args: [ + Call( + ExprCall { + range: 221..240, + func: Attribute( + ExprAttribute { + range: 221..238, + value: Constant( + ExprConstant { + range: 221..227, + value: Int( + 11, + ), + kind: None, + }, + ), + attr: Identifier { + id: "bit_length", + range: 228..238, }, - ), - attr: Identifier { - id: "bit_length", - range: 228..238, + ctx: Load, }, - ctx: Load, + ), + arguments: Arguments { + range: 238..240, + args: [], + keywords: [], }, - ), - args: [], - keywords: [], - }, - ), - ], - keywords: [], + }, + ), + ], + keywords: [], + }, }, ), }, @@ -391,8 +406,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 263..265, + args: [], + keywords: [], + }, }, ), }, @@ -431,8 +449,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 287..289, + args: [], + keywords: [], + }, }, ), }, @@ -504,8 +525,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 327..329, + args: [], + keywords: [], + }, }, ), }, @@ -639,16 +663,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kind: None, }, ), - args: [ - Name( - ExprName { - range: 388..390, - id: "no", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 387..391, + args: [ + Name( + ExprName { + range: 388..390, + id: "no", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap index b439b18abffd4..e567e1d4e4a7a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap @@ -1,49 +1,59 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ ClassDef( StmtClassDef { range: 0..98, + decorator_list: [], name: Identifier { id: "Foo", range: 6..9, }, - bases: [ - Name( - ExprName { - range: 10..11, - id: "A", - ctx: Load, - }, - ), - Name( - ExprName { - range: 13..14, - id: "B", - ctx: Load, - }, - ), - ], - keywords: [], + type_params: None, + arguments: Some( + Arguments { + range: 9..15, + args: [ + Name( + ExprName { + range: 10..11, + id: "A", + ctx: Load, + }, + ), + Name( + ExprName { + range: 13..14, + id: "B", + ctx: Load, + }, + ), + ], + keywords: [], + }, + ), body: [ FunctionDef( StmtFunctionDef { range: 18..44, + is_async: false, + decorator_list: [], name: Identifier { id: "__init__", range: 22..30, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 30..36, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 31..35, - def: Arg { + parameter: Parameter { range: 31..35, - arg: Identifier { + name: Identifier { id: "self", range: 31..35, }, @@ -56,6 +66,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -63,27 +74,27 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), FunctionDef( StmtFunctionDef { range: 46..98, + is_async: false, + decorator_list: [], name: Identifier { id: "method_with_default", range: 50..69, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 69..90, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 70..74, - def: Arg { + parameter: Parameter { range: 70..74, - arg: Identifier { + name: Identifier { id: "self", range: 70..74, }, @@ -91,11 +102,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, default: None, }, - ArgWithDefault { + ParameterWithDefault { range: 76..89, - def: Arg { + parameter: Parameter { range: 76..79, - arg: Identifier { + name: Identifier { id: "arg", range: 76..79, }, @@ -106,7 +117,10 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ExprConstant { range: 80..89, value: Str( - "default", + StringConstant { + value: "default", + implicit_concatenated: false, + }, ), kind: None, }, @@ -118,6 +132,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -125,14 +140,9 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), ], - type_params: [], - decorator_list: [], }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap index f0dba8f78f644..7353f1cc141be 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap @@ -1,17 +1,40 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ ClassDef( StmtClassDef { range: 10..29, + decorator_list: [], name: Identifier { id: "Foo", range: 16..19, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 19..22, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 20..21, + name: Identifier { + id: "T", + range: 20..21, + }, + bound: None, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 22..24, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -26,30 +49,48 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 20..21, - name: Identifier { - id: "T", - range: 20..21, - }, - bound: None, - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 52..76, + decorator_list: [], name: Identifier { id: "Foo", range: 58..61, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 61..69, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 62..68, + name: Identifier { + id: "T", + range: 62..63, + }, + bound: Some( + Name( + ExprName { + range: 65..68, + id: "str", + ctx: Load, + }, + ), + ), + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 69..71, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -64,38 +105,63 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 62..68, - name: Identifier { - id: "T", - range: 62..63, - }, - bound: Some( - Name( - ExprName { - range: 65..68, - id: "str", - ctx: Load, - }, - ), - ), - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 105..138, + decorator_list: [], name: Identifier { id: "Foo", range: 111..114, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 114..131, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 115..130, + name: Identifier { + id: "T", + range: 115..116, + }, + bound: Some( + Tuple( + ExprTuple { + range: 118..130, + elts: [ + Name( + ExprName { + range: 119..122, + id: "str", + ctx: Load, + }, + ), + Name( + ExprName { + range: 124..129, + id: "bytes", + ctx: Load, + }, + ), + ], + ctx: Load, + }, + ), + ), + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 131..133, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -110,53 +176,50 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 115..130, - name: Identifier { - id: "T", - range: 115..116, - }, - bound: Some( - Tuple( - ExprTuple { - range: 118..130, - elts: [ - Name( - ExprName { - range: 119..122, - id: "str", - ctx: Load, - }, - ), - Name( - ExprName { - range: 124..129, - id: "bytes", - ctx: Load, - }, - ), - ], - ctx: Load, - }, - ), - ), - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 159..181, + decorator_list: [], name: Identifier { id: "Foo", range: 165..168, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 168..174, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 169..170, + name: Identifier { + id: "T", + range: 169..170, + }, + bound: None, + }, + ), + TypeVar( + TypeParamTypeVar { + range: 172..173, + name: Identifier { + id: "U", + range: 172..173, + }, + bound: None, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 174..176, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -171,40 +234,50 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 169..170, - name: Identifier { - id: "T", - range: 169..170, - }, - bound: None, - }, - ), - TypeVar( - TypeParamTypeVar { - range: 172..173, - name: Identifier { - id: "U", - range: 172..173, - }, - bound: None, - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 200..223, + decorator_list: [], name: Identifier { id: "Foo", range: 206..209, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 209..216, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 210..211, + name: Identifier { + id: "T", + range: 210..211, + }, + bound: None, + }, + ), + TypeVar( + TypeParamTypeVar { + range: 213..214, + name: Identifier { + id: "U", + range: 213..214, + }, + bound: None, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 216..218, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -219,40 +292,39 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 210..211, - name: Identifier { - id: "T", - range: 210..211, - }, - bound: None, - }, - ), - TypeVar( - TypeParamTypeVar { - range: 213..214, - name: Identifier { - id: "U", - range: 213..214, - }, - bound: None, - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 240..261, + decorator_list: [], name: Identifier { id: "Foo", range: 246..249, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 249..254, + type_params: [ + TypeVarTuple( + TypeParamTypeVarTuple { + range: 250..253, + name: Identifier { + id: "Ts", + range: 251..253, + }, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 254..256, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -267,29 +339,39 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVarTuple( - TypeParamTypeVarTuple { - range: 250..253, - name: Identifier { - id: "Ts", - range: 251..253, - }, - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 275..296, + decorator_list: [], name: Identifier { id: "Foo", range: 281..284, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 284..289, + type_params: [ + ParamSpec( + TypeParamParamSpec { + range: 285..288, + name: Identifier { + id: "P", + range: 287..288, + }, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 289..291, + args: [], + keywords: [], + }, + ), body: [ Expr( StmtExpr { @@ -304,29 +386,76 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - ParamSpec( - TypeParamParamSpec { - range: 285..288, - name: Identifier { - id: "P", - range: 287..288, - }, - }, - ), - ], - decorator_list: [], }, ), ClassDef( StmtClassDef { range: 312..351, + decorator_list: [], name: Identifier { id: "Foo", range: 318..321, }, - bases: [], - keywords: [], + type_params: Some( + TypeParams { + range: 321..341, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 322..323, + name: Identifier { + id: "X", + range: 322..323, + }, + bound: None, + }, + ), + TypeVar( + TypeParamTypeVar { + range: 325..331, + name: Identifier { + id: "Y", + range: 325..326, + }, + bound: Some( + Name( + ExprName { + range: 328..331, + id: "str", + ctx: Load, + }, + ), + ), + }, + ), + TypeVarTuple( + TypeParamTypeVarTuple { + range: 333..335, + name: Identifier { + id: "U", + range: 334..335, + }, + }, + ), + ParamSpec( + TypeParamParamSpec { + range: 337..340, + name: Identifier { + id: "P", + range: 339..340, + }, + }, + ), + ], + }, + ), + arguments: Some( + Arguments { + range: 341..343, + args: [], + keywords: [], + }, + ), body: [ Pass( StmtPass { @@ -334,55 +463,6 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 322..323, - name: Identifier { - id: "X", - range: 322..323, - }, - bound: None, - }, - ), - TypeVar( - TypeParamTypeVar { - range: 325..331, - name: Identifier { - id: "Y", - range: 325..326, - }, - bound: Some( - Name( - ExprName { - range: 328..331, - id: "str", - ctx: Load, - }, - ), - ), - }, - ), - TypeVarTuple( - TypeParamTypeVarTuple { - range: 333..335, - name: Identifier { - id: "U", - range: 334..335, - }, - }, - ), - ParamSpec( - TypeParamParamSpec { - range: 337..340, - name: Identifier { - id: "P", - range: 339..340, - }, - }, - ), - ], - decorator_list: [], }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap index cc110c3f272ef..f65e153bea1a3 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap @@ -6,20 +6,24 @@ expression: parse_ast Expr( StmtExpr { range: 0..14, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..14, values: [ Constant( ExprConstant { range: 2..13, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: false, + }, ), kind: None, }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap index fff68f3279fd4..cf0f7df886cd7 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap @@ -1,24 +1,27 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ FunctionDef( StmtFunctionDef { range: 0..20, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 4..8, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 8..11, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 9..10, - def: Arg { + parameter: Parameter { range: 9..10, - arg: Identifier { + name: Identifier { id: "a", range: 9..10, }, @@ -31,6 +34,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Expr( StmtExpr { @@ -45,27 +49,43 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [], }, ), FunctionDef( StmtFunctionDef { range: 22..53, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 26..30, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 30..33, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 31..32, + name: Identifier { + id: "T", + range: 31..32, + }, + bound: None, + }, + ), + ], + }, + ), + parameters: Parameters { range: 33..39, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 34..38, - def: Arg { + parameter: Parameter { range: 34..38, - arg: Identifier { + name: Identifier { id: "a", range: 34..35, }, @@ -86,6 +106,15 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: Some( + Name( + ExprName { + range: 43..44, + id: "T", + ctx: Load, + }, + ), + ), body: [ Expr( StmtExpr { @@ -100,46 +129,51 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: Some( - Name( - ExprName { - range: 43..44, - id: "T", - ctx: Load, - }, - ), - ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 31..32, - name: Identifier { - id: "T", - range: 31..32, - }, - bound: None, - }, - ), - ], }, ), FunctionDef( StmtFunctionDef { range: 55..91, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 59..63, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 63..71, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 64..70, + name: Identifier { + id: "T", + range: 64..65, + }, + bound: Some( + Name( + ExprName { + range: 67..70, + id: "str", + ctx: Load, + }, + ), + ), + }, + ), + ], + }, + ), + parameters: Parameters { range: 71..77, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 72..76, - def: Arg { + parameter: Parameter { range: 72..76, - arg: Identifier { + name: Identifier { id: "a", range: 72..73, }, @@ -160,6 +194,15 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: Some( + Name( + ExprName { + range: 81..82, + id: "T", + ctx: Load, + }, + ), + ), body: [ Expr( StmtExpr { @@ -174,54 +217,66 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: Some( - Name( - ExprName { - range: 81..82, - id: "T", - ctx: Load, - }, - ), - ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 64..70, - name: Identifier { - id: "T", - range: 64..65, - }, - bound: Some( - Name( - ExprName { - range: 67..70, - id: "str", - ctx: Load, - }, - ), - ), - }, - ), - ], }, ), FunctionDef( StmtFunctionDef { range: 93..138, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 97..101, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 101..118, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 102..117, + name: Identifier { + id: "T", + range: 102..103, + }, + bound: Some( + Tuple( + ExprTuple { + range: 105..117, + elts: [ + Name( + ExprName { + range: 106..109, + id: "str", + ctx: Load, + }, + ), + Name( + ExprName { + range: 111..116, + id: "bytes", + ctx: Load, + }, + ), + ], + ctx: Load, + }, + ), + ), + }, + ), + ], + }, + ), + parameters: Parameters { range: 118..124, posonlyargs: [], args: [ - ArgWithDefault { + ParameterWithDefault { range: 119..123, - def: Arg { + parameter: Parameter { range: 119..123, - arg: Identifier { + name: Identifier { id: "a", range: 119..120, }, @@ -242,6 +297,15 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: Some( + Name( + ExprName { + range: 128..129, + id: "T", + ctx: Load, + }, + ), + ), body: [ Expr( StmtExpr { @@ -256,68 +320,41 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: Some( - Name( - ExprName { - range: 128..129, - id: "T", - ctx: Load, - }, - ), - ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 102..117, - name: Identifier { - id: "T", - range: 102..103, - }, - bound: Some( - Tuple( - ExprTuple { - range: 105..117, - elts: [ - Name( - ExprName { - range: 106..109, - id: "str", - ctx: Load, - }, - ), - Name( - ExprName { - range: 111..116, - id: "bytes", - ctx: Load, - }, - ), - ], - ctx: Load, - }, - ), - ), - }, - ), - ], }, ), FunctionDef( StmtFunctionDef { range: 140..171, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 144..148, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 148..153, + type_params: [ + TypeVarTuple( + TypeParamTypeVarTuple { + range: 149..152, + name: Identifier { + id: "Ts", + range: 150..152, + }, + }, + ), + ], + }, + ), + parameters: Parameters { range: 153..162, posonlyargs: [], args: [], vararg: Some( - Arg { + Parameter { range: 155..161, - arg: Identifier { + name: Identifier { id: "a", range: 155..156, }, @@ -341,6 +378,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Expr( StmtExpr { @@ -355,36 +393,41 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [ - TypeVarTuple( - TypeParamTypeVarTuple { - range: 149..152, - name: Identifier { - id: "Ts", - range: 150..152, - }, - }, - ), - ], }, ), FunctionDef( StmtFunctionDef { range: 173..230, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 177..181, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 181..186, + type_params: [ + ParamSpec( + TypeParamParamSpec { + range: 182..185, + name: Identifier { + id: "P", + range: 184..185, + }, + }, + ), + ], + }, + ), + parameters: Parameters { range: 186..221, posonlyargs: [], args: [], vararg: Some( - Arg { + Parameter { range: 188..200, - arg: Identifier { + name: Identifier { id: "args", range: 188..192, }, @@ -411,9 +454,9 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ), kwonlyargs: [], kwarg: Some( - Arg { + Parameter { range: 204..220, - arg: Identifier { + name: Identifier { id: "kwargs", range: 204..210, }, @@ -439,6 +482,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), }, + returns: None, body: [ Expr( StmtExpr { @@ -453,29 +497,71 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [ - ParamSpec( - TypeParamParamSpec { - range: 182..185, - name: Identifier { - id: "P", - range: 184..185, - }, - }, - ), - ], }, ), FunctionDef( StmtFunctionDef { range: 232..273, + is_async: false, + decorator_list: [], name: Identifier { id: "func", range: 236..240, }, - args: Arguments { + type_params: Some( + TypeParams { + range: 240..261, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 241..242, + name: Identifier { + id: "T", + range: 241..242, + }, + bound: None, + }, + ), + TypeVar( + TypeParamTypeVar { + range: 244..250, + name: Identifier { + id: "U", + range: 244..245, + }, + bound: Some( + Name( + ExprName { + range: 247..250, + id: "str", + ctx: Load, + }, + ), + ), + }, + ), + TypeVarTuple( + TypeParamTypeVarTuple { + range: 252..255, + name: Identifier { + id: "Ts", + range: 253..255, + }, + }, + ), + ParamSpec( + TypeParamParamSpec { + range: 257..260, + name: Identifier { + id: "P", + range: 259..260, + }, + }, + ), + ], + }, + ), + parameters: Parameters { range: 261..263, posonlyargs: [], args: [], @@ -483,6 +569,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" kwonlyargs: [], kwarg: None, }, + returns: None, body: [ Pass( StmtPass { @@ -490,56 +577,6 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" }, ), ], - decorator_list: [], - returns: None, - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 241..242, - name: Identifier { - id: "T", - range: 241..242, - }, - bound: None, - }, - ), - TypeVar( - TypeParamTypeVar { - range: 244..250, - name: Identifier { - id: "U", - range: 244..245, - }, - bound: Some( - Name( - ExprName { - range: 247..250, - id: "str", - ctx: Load, - }, - ), - ), - }, - ), - TypeVarTuple( - TypeParamTypeVarTuple { - range: 252..255, - name: Identifier { - id: "Ts", - range: 253..255, - }, - }, - ), - ParamSpec( - TypeParamParamSpec { - range: 257..260, - name: Identifier { - id: "P", - range: 259..260, - }, - }, - ), - ], }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap index bad3e453b3511..dbf2ae2258206 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap @@ -16,37 +16,43 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 8..20, - value: Str( - "positional", - ), - kind: None, - }, - ), - ], - keywords: [ - Keyword { - range: 22..31, - arg: Some( - Identifier { - id: "keyword", - range: 22..29, - }, - ), - value: Constant( + arguments: Arguments { + range: 7..32, + args: [ + Constant( ExprConstant { - range: 30..31, - value: Int( - 2, + range: 8..20, + value: Str( + StringConstant { + value: "positional", + implicit_concatenated: false, + }, ), kind: None, }, ), - }, - ], + ], + keywords: [ + Keyword { + range: 22..31, + arg: Some( + Identifier { + id: "keyword", + range: 22..29, + }, + ), + value: Constant( + ExprConstant { + range: 30..31, + value: Int( + 2, + ), + kind: None, + }, + ), + }, + ], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap index cd7629d670d61..4401fd6c8428a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap @@ -9,39 +9,41 @@ expression: parse_ast value: Lambda( ExprLambda { range: 0..18, - args: Arguments { - range: 7..11, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 7..8, - def: Arg { + parameters: Some( + Parameters { + range: 7..11, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 7..8, - arg: Identifier { - id: "x", + parameter: Parameter { range: 7..8, + name: Identifier { + id: "x", + range: 7..8, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ArgWithDefault { - range: 10..11, - def: Arg { + ParameterWithDefault { range: 10..11, - arg: Identifier { - id: "y", + parameter: Parameter { range: 10..11, + name: Identifier { + id: "y", + range: 10..11, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), body: BinOp( ExprBinOp { range: 13..18, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap index 4910981fc978f..c8c73c80c88bb 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap @@ -9,14 +9,7 @@ expression: parse_ast value: Lambda( ExprLambda { range: 0..9, - args: Arguments { - range: 6..6, - posonlyargs: [], - args: [], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + parameters: None, body: Constant( ExprConstant { range: 8..9, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap index 22929503adc01..583746f9dd31e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap @@ -16,27 +16,33 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 6..19, - value: Str( - "Hello world", - ), - kind: None, - }, - ), - Constant( - ExprConstant { - range: 21..22, - value: Int( - 2, - ), - kind: None, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 5..23, + args: [ + Constant( + ExprConstant { + range: 6..19, + value: Str( + StringConstant { + value: "Hello world", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + Constant( + ExprConstant { + range: 21..22, + value: Int( + 2, + ), + kind: None, + }, + ), + ], + keywords: [], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap index 23684e9c1662f..fab7de1e6ac76 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap @@ -16,18 +16,24 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 6..19, - value: Str( - "Hello world", - ), - kind: None, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 5..20, + args: [ + Constant( + ExprConstant { + range: 6..19, + value: Str( + StringConstant { + value: "Hello world", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + ], + keywords: [], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap index 21c12fb897bef..301501a7d9f15 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..13, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap index a0bc32044f8bb..2186cc9152191 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap @@ -1,6 +1,6 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ TypeAlias( @@ -13,7 +13,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 10..13, @@ -33,7 +33,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: BinOp( ExprBinOp { range: 23..32, @@ -66,7 +66,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: BinOp( ExprBinOp { range: 42..61, @@ -82,7 +82,10 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ExprConstant { range: 48..61, value: Str( - "ForwardRefY", + StringConstant { + value: "ForwardRefY", + implicit_concatenated: false, + }, ), kind: None, }, @@ -101,18 +104,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 69..70, - name: Identifier { - id: "T", - range: 69..70, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 68..71, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 69..70, + name: Identifier { + id: "T", + range: 69..70, + }, + bound: None, + }, + ), + ], + }, + ), value: BinOp( ExprBinOp { range: 74..88, @@ -171,18 +179,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 109..110, - name: Identifier { - id: "T", - range: 109..110, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 108..111, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 109..110, + name: Identifier { + id: "T", + range: 109..110, + }, + bound: None, + }, + ), + ], + }, + ), value: Name( ExprName { range: 114..117, @@ -202,18 +215,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 125..126, - name: Identifier { - id: "T", - range: 125..126, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 124..127, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 125..126, + name: Identifier { + id: "T", + range: 125..126, + }, + bound: None, + }, + ), + ], + }, + ), value: BinOp( ExprBinOp { range: 130..146, @@ -272,36 +290,41 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 154..155, - name: Identifier { - id: "T", - range: 154..155, - }, - bound: None, - }, - ), - TypeVarTuple( - TypeParamTypeVarTuple { - range: 157..160, - name: Identifier { - id: "Ts", - range: 158..160, - }, - }, - ), - ParamSpec( - TypeParamParamSpec { - range: 162..165, - name: Identifier { - id: "P", - range: 164..165, - }, - }, - ), - ], + type_params: Some( + TypeParams { + range: 153..166, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 154..155, + name: Identifier { + id: "T", + range: 154..155, + }, + bound: None, + }, + ), + TypeVarTuple( + TypeParamTypeVarTuple { + range: 157..160, + name: Identifier { + id: "Ts", + range: 158..160, + }, + }, + ), + ParamSpec( + TypeParamParamSpec { + range: 162..165, + name: Identifier { + id: "P", + range: 164..165, + }, + }, + ), + ], + }, + ), value: Tuple( ExprTuple { range: 169..179, @@ -343,44 +366,49 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 187..193, - name: Identifier { - id: "T", - range: 187..188, - }, - bound: Some( - Name( - ExprName { - range: 190..193, - id: "int", - ctx: Load, + type_params: Some( + TypeParams { + range: 186..204, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 187..193, + name: Identifier { + id: "T", + range: 187..188, }, - ), + bound: Some( + Name( + ExprName { + range: 190..193, + id: "int", + ctx: Load, + }, + ), + ), + }, ), - }, - ), - TypeVarTuple( - TypeParamTypeVarTuple { - range: 195..198, - name: Identifier { - id: "Ts", - range: 196..198, - }, - }, - ), - ParamSpec( - TypeParamParamSpec { - range: 200..203, - name: Identifier { - id: "P", - range: 202..203, - }, - }, - ), - ], + TypeVarTuple( + TypeParamTypeVarTuple { + range: 195..198, + name: Identifier { + id: "Ts", + range: 196..198, + }, + }, + ), + ParamSpec( + TypeParamParamSpec { + range: 200..203, + name: Identifier { + id: "P", + range: 202..203, + }, + }, + ), + ], + }, + ), value: Tuple( ExprTuple { range: 207..217, @@ -422,59 +450,64 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 225..238, - name: Identifier { - id: "T", - range: 225..226, - }, - bound: Some( - Tuple( - ExprTuple { - range: 228..238, - elts: [ - Name( - ExprName { - range: 229..232, - id: "int", - ctx: Load, - }, - ), - Name( - ExprName { - range: 234..237, - id: "str", - ctx: Load, - }, - ), - ], - ctx: Load, + type_params: Some( + TypeParams { + range: 224..249, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 225..238, + name: Identifier { + id: "T", + range: 225..226, }, - ), + bound: Some( + Tuple( + ExprTuple { + range: 228..238, + elts: [ + Name( + ExprName { + range: 229..232, + id: "int", + ctx: Load, + }, + ), + Name( + ExprName { + range: 234..237, + id: "str", + ctx: Load, + }, + ), + ], + ctx: Load, + }, + ), + ), + }, ), - }, - ), - TypeVarTuple( - TypeParamTypeVarTuple { - range: 240..243, - name: Identifier { - id: "Ts", - range: 241..243, - }, - }, - ), - ParamSpec( - TypeParamParamSpec { - range: 245..248, - name: Identifier { - id: "P", - range: 247..248, - }, - }, - ), - ], + TypeVarTuple( + TypeParamTypeVarTuple { + range: 240..243, + name: Identifier { + id: "Ts", + range: 241..243, + }, + }, + ), + ParamSpec( + TypeParamParamSpec { + range: 245..248, + name: Identifier { + id: "P", + range: 247..248, + }, + }, + ), + ], + }, + ), value: Tuple( ExprTuple { range: 252..262, @@ -516,7 +549,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 305..308, @@ -536,7 +569,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 322..325, @@ -556,7 +589,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 338..341, @@ -576,7 +609,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 378..382, @@ -596,7 +629,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 394..399, @@ -616,7 +649,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 411..415, @@ -636,7 +669,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 451..454, @@ -656,7 +689,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 467..470, @@ -676,7 +709,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 483..486, @@ -696,7 +729,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [], + type_params: None, value: Name( ExprName { range: 502..505, @@ -716,18 +749,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 521..522, - name: Identifier { - id: "T", - range: 521..522, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 520..523, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 521..522, + name: Identifier { + id: "T", + range: 521..522, + }, + bound: None, + }, + ), + ], + }, + ), value: Name( ExprName { range: 526..527, @@ -747,18 +785,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 542..543, - name: Identifier { - id: "T", - range: 542..543, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 541..544, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 542..543, + name: Identifier { + id: "T", + range: 542..543, + }, + bound: None, + }, + ), + ], + }, + ), value: Name( ExprName { range: 547..548, @@ -778,18 +821,23 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Store, }, ), - type_params: [ - TypeVar( - TypeParamTypeVar { - range: 556..557, - name: Identifier { - id: "T", - range: 556..557, - }, - bound: None, - }, - ), - ], + type_params: Some( + TypeParams { + range: 555..558, + type_params: [ + TypeVar( + TypeParamTypeVar { + range: 556..557, + name: Identifier { + id: "T", + range: 556..557, + }, + bound: None, + }, + ), + ], + }, + ), value: Name( ExprName { range: 567..568, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap index 500ff2ab6b0e1..a29d01b17a164 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap @@ -522,7 +522,10 @@ expression: parse_ast ExprConstant { range: 484..489, value: Str( - "seq", + StringConstant { + value: "seq", + implicit_concatenated: false, + }, ), kind: None, }, @@ -552,7 +555,10 @@ expression: parse_ast ExprConstant { range: 518..523, value: Str( - "map", + StringConstant { + value: "map", + implicit_concatenated: false, + }, ), kind: None, }, @@ -857,7 +863,10 @@ expression: parse_ast ExprConstant { range: 664..667, value: Str( - "X", + StringConstant { + value: "X", + implicit_concatenated: false, + }, ), kind: None, }, @@ -1443,8 +1452,11 @@ expression: parse_ast ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 1130..1132, + args: [], + keywords: [], + }, }, ), cases: [ @@ -1614,7 +1626,10 @@ expression: parse_ast ExprConstant { range: 1287..1292, value: Str( - "foo", + StringConstant { + value: "foo", + implicit_concatenated: false, + }, ), kind: None, }, @@ -2562,7 +2577,10 @@ expression: parse_ast ExprConstant { range: 2036..2038, value: Str( - "", + StringConstant { + value: "", + implicit_concatenated: false, + }, ), kind: None, }, @@ -2608,7 +2626,10 @@ expression: parse_ast ExprConstant { range: 2064..2066, value: Str( - "", + StringConstant { + value: "", + implicit_concatenated: false, + }, ), kind: None, }, @@ -3248,7 +3269,10 @@ expression: parse_ast ExprConstant { range: 2449..2452, value: Str( - "X", + StringConstant { + value: "X", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap index 45f5d29a8947d..e3fd432492174 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap @@ -21,18 +21,21 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 26..27, - value: Int( - 1, - ), - kind: None, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 25..28, + args: [ + Constant( + ExprConstant { + range: 26..27, + value: Int( + 1, + ), + kind: None, + }, + ), + ], + keywords: [], + }, }, ), ), @@ -73,55 +76,65 @@ expression: parse_ast ctx: Load, }, ), - args: [ - JoinedStr( - ExprJoinedStr { - range: 62..81, - values: [ - Constant( - ExprConstant { - range: 64..71, - value: Str( - "caught ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 71..80, - value: Call( - ExprCall { - range: 72..79, - func: Name( - ExprName { - range: 72..76, - id: "type", - ctx: Load, - }, - ), - args: [ - Name( + arguments: Arguments { + range: 61..82, + args: [ + FString( + ExprFString { + range: 62..81, + values: [ + Constant( + ExprConstant { + range: 64..71, + value: Str( + StringConstant { + value: "caught ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 71..80, + value: Call( + ExprCall { + range: 72..79, + func: Name( ExprName { - range: 77..78, - id: "e", + range: 72..76, + id: "type", ctx: Load, }, ), - ], - keywords: [], - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 76..79, + args: [ + Name( + ExprName { + range: 77..78, + id: "e", + ctx: Load, + }, + ), + ], + keywords: [], + }, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -161,55 +174,65 @@ expression: parse_ast ctx: Load, }, ), - args: [ - JoinedStr( - ExprJoinedStr { - range: 114..133, - values: [ - Constant( - ExprConstant { - range: 116..123, - value: Str( - "caught ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 123..132, - value: Call( - ExprCall { - range: 124..131, - func: Name( - ExprName { - range: 124..128, - id: "type", - ctx: Load, - }, - ), - args: [ - Name( + arguments: Arguments { + range: 113..134, + args: [ + FString( + ExprFString { + range: 114..133, + values: [ + Constant( + ExprConstant { + range: 116..123, + value: Str( + StringConstant { + value: "caught ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 123..132, + value: Call( + ExprCall { + range: 124..131, + func: Name( ExprName { - range: 129..130, - id: "e", + range: 124..128, + id: "type", ctx: Load, }, ), - ], - keywords: [], - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 128..131, + args: [ + Name( + ExprName { + range: 129..130, + id: "e", + ctx: Load, + }, + ), + ], + keywords: [], + }, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -220,6 +243,7 @@ expression: parse_ast ], orelse: [], finalbody: [], + is_star: false, }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap index 37377fa47ab79..7940ea7359489 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap @@ -3,8 +3,8 @@ source: crates/ruff_python_parser/src/parser.rs expression: parse_ast --- [ - TryStar( - StmtTryStar { + Try( + StmtTry { range: 0..260, body: [ Raise( @@ -21,122 +21,140 @@ expression: parse_ast ctx: Load, }, ), - args: [ - Constant( - ExprConstant { - range: 30..34, - value: Str( - "eg", - ), - kind: None, - }, - ), - List( - ExprList { - range: 44..97, - elts: [ - Call( - ExprCall { - range: 45..58, - func: Name( - ExprName { - range: 45..55, - id: "ValueError", - ctx: Load, - }, - ), - args: [ - Constant( - ExprConstant { - range: 56..57, - value: Int( - 1, - ), - kind: None, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 29..98, + args: [ + Constant( + ExprConstant { + range: 30..34, + value: Str( + StringConstant { + value: "eg", + implicit_concatenated: false, }, ), - Call( - ExprCall { - range: 60..72, - func: Name( - ExprName { - range: 60..69, - id: "TypeError", - ctx: Load, - }, - ), - args: [ - Constant( - ExprConstant { - range: 70..71, - value: Int( - 2, - ), - kind: None, + kind: None, + }, + ), + List( + ExprList { + range: 44..97, + elts: [ + Call( + ExprCall { + range: 45..58, + func: Name( + ExprName { + range: 45..55, + id: "ValueError", + ctx: Load, }, ), - ], - keywords: [], - }, - ), - Call( - ExprCall { - range: 74..84, - func: Name( - ExprName { - range: 74..81, - id: "OSError", - ctx: Load, - }, - ), - args: [ - Constant( - ExprConstant { - range: 82..83, - value: Int( - 3, + arguments: Arguments { + range: 55..58, + args: [ + Constant( + ExprConstant { + range: 56..57, + value: Int( + 1, + ), + kind: None, + }, ), - kind: None, + ], + keywords: [], + }, + }, + ), + Call( + ExprCall { + range: 60..72, + func: Name( + ExprName { + range: 60..69, + id: "TypeError", + ctx: Load, }, ), - ], - keywords: [], - }, - ), - Call( - ExprCall { - range: 86..96, - func: Name( - ExprName { - range: 86..93, - id: "OSError", - ctx: Load, + arguments: Arguments { + range: 69..72, + args: [ + Constant( + ExprConstant { + range: 70..71, + value: Int( + 2, + ), + kind: None, + }, + ), + ], + keywords: [], }, - ), - args: [ - Constant( - ExprConstant { - range: 94..95, - value: Int( - 4, + }, + ), + Call( + ExprCall { + range: 74..84, + func: Name( + ExprName { + range: 74..81, + id: "OSError", + ctx: Load, + }, + ), + arguments: Arguments { + range: 81..84, + args: [ + Constant( + ExprConstant { + range: 82..83, + value: Int( + 3, + ), + kind: None, + }, ), - kind: None, + ], + keywords: [], + }, + }, + ), + Call( + ExprCall { + range: 86..96, + func: Name( + ExprName { + range: 86..93, + id: "OSError", + ctx: Load, }, ), - ], - keywords: [], - }, - ), - ], - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 93..96, + args: [ + Constant( + ExprConstant { + range: 94..95, + value: Int( + 4, + ), + kind: None, + }, + ), + ], + keywords: [], + }, + }, + ), + ], + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), ), @@ -177,89 +195,102 @@ expression: parse_ast ctx: Load, }, ), - args: [ - JoinedStr( - ExprJoinedStr { - range: 133..179, - values: [ - Constant( - ExprConstant { - range: 135..142, - value: Str( - "caught ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 142..151, - value: Call( - ExprCall { - range: 143..150, - func: Name( - ExprName { - range: 143..147, - id: "type", - ctx: Load, + arguments: Arguments { + range: 132..180, + args: [ + FString( + ExprFString { + range: 133..179, + values: [ + Constant( + ExprConstant { + range: 135..142, + value: Str( + StringConstant { + value: "caught ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 142..151, + value: Call( + ExprCall { + range: 143..150, + func: Name( + ExprName { + range: 143..147, + id: "type", + ctx: Load, + }, + ), + arguments: Arguments { + range: 147..150, + args: [ + Name( + ExprName { + range: 148..149, + id: "e", + ctx: Load, + }, + ), + ], + keywords: [], }, - ), - args: [ - Name( + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + Constant( + ExprConstant { + range: 151..164, + value: Str( + StringConstant { + value: " with nested ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 164..178, + value: Attribute( + ExprAttribute { + range: 165..177, + value: Name( ExprName { - range: 148..149, + range: 165..166, id: "e", ctx: Load, }, ), - ], - keywords: [], - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - Constant( - ExprConstant { - range: 151..164, - value: Str( - " with nested ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 164..178, - value: Attribute( - ExprAttribute { - range: 165..177, - value: Name( - ExprName { - range: 165..166, - id: "e", - ctx: Load, + attr: Identifier { + id: "exceptions", + range: 167..177, }, - ), - attr: Identifier { - id: "exceptions", - range: 167..177, + ctx: Load, }, - ctx: Load, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - }, - ), - ], - keywords: [], + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -299,89 +330,102 @@ expression: parse_ast ctx: Load, }, ), - args: [ - JoinedStr( - ExprJoinedStr { - range: 213..259, - values: [ - Constant( - ExprConstant { - range: 215..222, - value: Str( - "caught ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 222..231, - value: Call( - ExprCall { - range: 223..230, - func: Name( - ExprName { - range: 223..227, - id: "type", - ctx: Load, + arguments: Arguments { + range: 212..260, + args: [ + FString( + ExprFString { + range: 213..259, + values: [ + Constant( + ExprConstant { + range: 215..222, + value: Str( + StringConstant { + value: "caught ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 222..231, + value: Call( + ExprCall { + range: 223..230, + func: Name( + ExprName { + range: 223..227, + id: "type", + ctx: Load, + }, + ), + arguments: Arguments { + range: 227..230, + args: [ + Name( + ExprName { + range: 228..229, + id: "e", + ctx: Load, + }, + ), + ], + keywords: [], }, - ), - args: [ - Name( + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + Constant( + ExprConstant { + range: 231..244, + value: Str( + StringConstant { + value: " with nested ", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 244..258, + value: Attribute( + ExprAttribute { + range: 245..257, + value: Name( ExprName { - range: 228..229, + range: 245..246, id: "e", ctx: Load, }, ), - ], - keywords: [], - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - Constant( - ExprConstant { - range: 231..244, - value: Str( - " with nested ", - ), - kind: None, - }, - ), - FormattedValue( - ExprFormattedValue { - range: 244..258, - value: Attribute( - ExprAttribute { - range: 245..257, - value: Name( - ExprName { - range: 245..246, - id: "e", - ctx: Load, + attr: Identifier { + id: "exceptions", + range: 247..257, }, - ), - attr: Identifier { - id: "exceptions", - range: 247..257, + ctx: Load, }, - ctx: Load, - }, - ), - debug_text: None, - conversion: None, - format_spec: None, - }, - ), - ], - }, - ), - ], - keywords: [], + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -392,6 +436,7 @@ expression: parse_ast ], orelse: [], finalbody: [], + is_star: true, }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap index 76001aa6709de..8b10562a32c67 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap @@ -1,6 +1,6 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ Expr( @@ -122,42 +122,45 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Starred( - ExprStarred { - range: 88..94, - value: BinOp( - ExprBinOp { - range: 89..94, - left: Name( - ExprName { - range: 89..90, - id: "a", - ctx: Load, - }, - ), - op: Add, - right: Name( - ExprName { - range: 93..94, - id: "b", - ctx: Load, - }, - ), - }, - ), - ctx: Load, - }, - ), - Name( - ExprName { - range: 96..97, - id: "c", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 87..98, + args: [ + Starred( + ExprStarred { + range: 88..94, + value: BinOp( + ExprBinOp { + range: 89..94, + left: Name( + ExprName { + range: 89..90, + id: "a", + ctx: Load, + }, + ), + op: Add, + right: Name( + ExprName { + range: 93..94, + id: "b", + ctx: Load, + }, + ), + }, + ), + ctx: Load, + }, + ), + Name( + ExprName { + range: 96..97, + id: "c", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -283,22 +286,25 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - UnaryOp( - ExprUnaryOp { - range: 214..216, - op: USub, - operand: Name( - ExprName { - range: 215..216, - id: "a", - ctx: Load, - }, - ), - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 213..217, + args: [ + UnaryOp( + ExprUnaryOp { + range: 214..216, + op: USub, + operand: Name( + ExprName { + range: 215..216, + id: "a", + ctx: Load, + }, + ), + }, + ), + ], + keywords: [], + }, }, ), op: Mult, @@ -339,8 +345,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 257..259, + args: [], + keywords: [], + }, }, ), attr: Identifier { @@ -368,16 +377,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Tuple( - ExprTuple { - range: 283..285, - elts: [], - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 282..286, + args: [ + Tuple( + ExprTuple { + range: 283..285, + elts: [], + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), attr: Identifier { @@ -405,16 +417,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Tuple( - ExprTuple { - range: 312..314, - elts: [], - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 311..316, + args: [ + Tuple( + ExprTuple { + range: 312..314, + elts: [], + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), attr: Identifier { @@ -563,8 +578,11 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [], + arguments: Arguments { + range: 450..452, + args: [], + keywords: [], + }, }, ), slice: Slice( @@ -645,27 +663,29 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" value: Lambda( ExprLambda { range: 507..535, - args: Arguments { - range: 514..519, - posonlyargs: [], - args: [ - ArgWithDefault { - range: 514..519, - def: Arg { + parameters: Some( + Parameters { + range: 514..519, + posonlyargs: [], + args: [ + ParameterWithDefault { range: 514..519, - arg: Identifier { - id: "query", + parameter: Parameter { range: 514..519, + name: Identifier { + id: "query", + range: 514..519, + }, + annotation: None, }, - annotation: None, + default: None, }, - default: None, - }, - ], - vararg: None, - kwonlyargs: [], - kwarg: None, - }, + ], + vararg: None, + kwonlyargs: [], + kwarg: None, + }, + ), body: Compare( ExprCompare { range: 521..535, @@ -707,33 +727,39 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Call( - ExprCall { - range: 542..550, - func: Name( - ExprName { - range: 542..546, - id: "type", - ctx: Load, - }, - ), - args: [ - Constant( - ExprConstant { - range: 547..549, - value: Int( - 12, - ), - kind: None, + arguments: Arguments { + range: 541..551, + args: [ + Call( + ExprCall { + range: 542..550, + func: Name( + ExprName { + range: 542..546, + id: "type", + ctx: Load, }, ), - ], - keywords: [], - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 546..550, + args: [ + Constant( + ExprConstant { + range: 547..549, + value: Int( + 12, + ), + kind: None, + }, + ), + ], + keywords: [], + }, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -751,16 +777,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Name( - ExprName { - range: 557..561, - id: "type", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 556..562, + args: [ + Name( + ExprName { + range: 557..561, + id: "type", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -825,16 +854,19 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [ - Name( - ExprName { - range: 594..595, - id: "b", - ctx: Load, - }, - ), - ], - keywords: [], + arguments: Arguments { + range: 593..596, + args: [ + Name( + ExprName { + range: 594..595, + id: "b", + ctx: Load, + }, + ), + ], + keywords: [], + }, }, ), }, @@ -852,25 +884,28 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" ctx: Load, }, ), - args: [], - keywords: [ - Keyword { - range: 607..614, - arg: Some( - Identifier { - id: "X", - range: 607..608, - }, - ), - value: Name( - ExprName { - range: 611..614, - id: "int", - ctx: Load, - }, - ), - }, - ], + arguments: Arguments { + range: 604..616, + args: [], + keywords: [ + Keyword { + range: 607..614, + arg: Some( + Identifier { + id: "X", + range: 607..608, + }, + ), + value: Name( + ExprName { + range: 611..614, + id: "int", + ctx: Load, + }, + ), + }, + ], + }, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap index 528eb65a1a526..891e02d91470f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap @@ -6,18 +6,21 @@ expression: parse_ast FunctionDef( StmtFunctionDef { range: 1..49, + is_async: false, + decorator_list: [], name: Identifier { id: "args_to_tuple", range: 5..18, }, - args: Arguments { + type_params: None, + parameters: Parameters { range: 18..30, posonlyargs: [], args: [], vararg: Some( - Arg { + Parameter { range: 20..29, - arg: Identifier { + name: Identifier { id: "args", range: 20..24, }, @@ -41,21 +44,6 @@ expression: parse_ast kwonlyargs: [], kwarg: None, }, - body: [ - Expr( - StmtExpr { - range: 46..49, - value: Constant( - ExprConstant { - range: 46..49, - value: Ellipsis, - kind: None, - }, - ), - }, - ), - ], - decorator_list: [], returns: Some( Subscript( ExprSubscript { @@ -84,7 +72,20 @@ expression: parse_ast }, ), ), - type_params: [], + body: [ + Expr( + StmtExpr { + range: 46..49, + value: Constant( + ExprConstant { + range: 46..49, + value: Ellipsis, + kind: None, + }, + ), + }, + ), + ], }, ), ] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap index 668b5381fe472..abae0fb4bcdb2 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap @@ -1,11 +1,12 @@ --- source: crates/ruff_python_parser/src/parser.rs -expression: "ast::Suite::parse(source, \"\").unwrap()" +expression: "parse_suite(source, \"\").unwrap()" --- [ With( StmtWith { range: 0..12, + is_async: false, items: [ WithItem { range: 5..6, @@ -33,6 +34,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 13..30, + is_async: false, items: [ WithItem { range: 18..24, @@ -68,6 +70,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 31..46, + is_async: false, items: [ WithItem { range: 36..37, @@ -108,6 +111,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 47..72, + is_async: false, items: [ WithItem { range: 52..58, @@ -164,6 +168,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 73..97, + is_async: false, items: [ WithItem { range: 78..91, @@ -214,6 +219,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 98..127, + is_async: false, items: [ WithItem { range: 103..121, @@ -272,6 +278,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 128..141, + is_async: false, items: [ WithItem { range: 133..135, @@ -297,6 +304,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 142..160, + is_async: false, items: [ WithItem { range: 147..154, @@ -330,6 +338,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 161..175, + is_async: false, items: [ WithItem { range: 167..168, @@ -357,6 +366,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 176..195, + is_async: false, items: [ WithItem { range: 181..189, @@ -392,6 +402,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 196..211, + is_async: false, items: [ WithItem { range: 202..203, @@ -419,6 +430,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 212..232, + is_async: false, items: [ WithItem { range: 217..226, @@ -462,6 +474,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 233..250, + is_async: false, items: [ WithItem { range: 239..243, @@ -502,6 +515,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 251..273, + is_async: false, items: [ WithItem { range: 256..267, @@ -554,6 +568,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 274..290, + is_async: false, items: [ WithItem { range: 279..284, @@ -593,6 +608,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 291..312, + is_async: false, items: [ WithItem { range: 296..306, @@ -640,6 +656,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 313..331, + is_async: false, items: [ WithItem { range: 318..325, @@ -688,6 +705,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 332..355, + is_async: false, items: [ WithItem { range: 337..349, @@ -744,6 +762,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 356..375, + is_async: false, items: [ WithItem { range: 361..369, @@ -783,6 +802,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 376..400, + is_async: false, items: [ WithItem { range: 381..394, @@ -830,6 +850,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 401..428, + is_async: false, items: [ WithItem { range: 406..422, @@ -898,6 +919,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 429..461, + is_async: false, items: [ WithItem { range: 434..455, @@ -974,6 +996,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 462..481, + is_async: false, items: [ WithItem { range: 468..474, @@ -1009,6 +1032,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 482..502, + is_async: false, items: [ WithItem { range: 488..494, @@ -1044,6 +1068,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 503..530, + is_async: false, items: [ WithItem { range: 509..515, @@ -1100,6 +1125,7 @@ expression: "ast::Suite::parse(source, \"\").unwrap()" With( StmtWith { range: 531..559, + is_async: false, items: [ WithItem { range: 537..543, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap index 11ee52f9fcce4..1d1aef73a6d11 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..15, value: Str( - "\u{8}", + StringConstant { + value: "\u{8}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap index 3d40adcad1461..5c4b9fda0f428 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..9, value: Str( - "\u{7}", + StringConstant { + value: "\u{7}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap index 6b57141008f34..f16ca7fce665d 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..21, value: Str( - "\r", + StringConstant { + value: "\r", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap index b172239e134e7..ba1969efc4fbc 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..45, value: Str( - "\u{89}", + StringConstant { + value: "\u{89}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap index 9bd9b1231dd78..4c9ef1738a359 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..12, value: Str( - "\u{7f}", + StringConstant { + value: "\u{7f}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap index 1b6f47e27aff9..7ec79b41ff8ff 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap @@ -10,264 +10,267 @@ expression: parse_ast ExprConstant { range: 0..738, value: Bytes( - [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100, - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120, - 121, - 122, - 123, - 124, - 125, - 126, - 127, - 128, - 129, - 130, - 131, - 132, - 133, - 134, - 135, - 136, - 137, - 138, - 139, - 140, - 141, - 142, - 143, - 144, - 145, - 146, - 147, - 148, - 149, - 150, - 151, - 152, - 153, - 154, - 155, - 156, - 157, - 158, - 159, - 160, - 161, - 162, - 163, - 164, - 165, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, - 181, - 182, - 183, - 184, - 185, - 186, - 187, - 188, - 189, - 190, - 191, - 192, - 193, - 194, - 195, - 196, - 197, - 198, - 199, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 209, - 210, - 211, - 212, - 213, - 214, - 215, - 216, - 217, - 218, - 219, - 220, - 221, - 222, - 223, - 224, - 225, - 226, - 227, - 228, - 229, - 230, - 231, - 232, - 233, - 234, - 235, - 236, - 237, - 238, - 239, - 240, - 241, - 242, - 243, - 244, - 245, - 246, - 247, - 248, - 249, - 250, - 251, - 252, - 253, - 254, - 255, - ], + BytesConstant { + value: [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap index 83ac74c136bef..7777636fcceea 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..12, value: Str( - "\u{1b}", + StringConstant { + value: "\u{1b}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap index c0da7019e992c..85a4d7705d38f 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap @@ -10,18 +10,21 @@ expression: parse_ast ExprConstant { range: 0..13, value: Bytes( - [ - 111, - 109, - 107, - 109, - 111, - 107, - 92, - 88, - 97, - 97, - ], + BytesConstant { + value: [ + 111, + 109, + 107, + 109, + 111, + 107, + 92, + 88, + 97, + 97, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap index 856ca446473e5..fc484d7a0753a 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap @@ -10,13 +10,16 @@ expression: parse_ast ExprConstant { range: 0..14, value: Bytes( - [ - 35, - 97, - 4, - 83, - 52, - ], + BytesConstant { + value: [ + 35, + 97, + 4, + 83, + 52, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap index 4773e4f2d384f..2ec6f9f544db1 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..15, value: Str( - "\u{c}", + StringConstant { + value: "\u{c}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap index 102e64ae26f83..6b4a1a92c819b 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..22, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..22, values: [ Constant( ExprConstant { range: 2..5, value: Str( - "aaa", + StringConstant { + value: "aaa", + implicit_concatenated: false, + }, ), kind: None, }, @@ -38,7 +41,10 @@ expression: parse_ast ExprConstant { range: 10..13, value: Str( - "ccc", + StringConstant { + value: "ccc", + implicit_concatenated: false, + }, ), kind: None, }, @@ -62,12 +68,16 @@ expression: parse_ast ExprConstant { range: 18..21, value: Str( - "eee", + StringConstant { + value: "eee", + implicit_concatenated: false, + }, ), kind: None, }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap index 0e906d3f0b2b2..d96a1cef58695 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..8, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..8, values: [ Constant( ExprConstant { range: 2..4, value: Str( - "\\", + StringConstant { + value: "\\", + implicit_concatenated: false, + }, ), kind: None, }, @@ -35,6 +38,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap index ff4ea50d1cf11..fe3c6d028e39c 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..8, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..8, values: [ Constant( ExprConstant { range: 2..4, value: Str( - "\n", + StringConstant { + value: "\n", + implicit_concatenated: false, + }, ), kind: None, }, @@ -35,6 +38,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap index 934f1939f64ae..35cff59a24ab1 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..9, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..9, values: [ Constant( ExprConstant { range: 3..5, value: Str( - "\\\n", + StringConstant { + value: "\\\n", + implicit_concatenated: false, + }, ), kind: None, }, @@ -35,6 +38,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap index dda8ce1dce1a6..655b3cc3d8af5 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap @@ -7,7 +7,10 @@ expression: parse_ast ExprConstant { range: 2..6, value: Str( - "mix ", + StringConstant { + value: "mix ", + implicit_concatenated: false, + }, ), kind: None, }, @@ -36,7 +39,10 @@ expression: parse_ast ExprConstant { range: 13..28, value: Str( - " with text and ", + StringConstant { + value: " with text and ", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap index 5363ceac88166..22b250a8ce768 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap @@ -21,20 +21,24 @@ expression: parse_ast ), conversion: None, format_spec: Some( - JoinedStr( - ExprJoinedStr { + FString( + ExprFString { range: 9..12, values: [ Constant( ExprConstant { range: 9..12, value: Str( - ">10", + StringConstant { + value: ">10", + implicit_concatenated: false, + }, ), kind: None, }, ), ], + implicit_concatenated: false, }, ), ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap index 4f176ac117dee..0b711c8cc91a3 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..11, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..11, values: [ Constant( ExprConstant { range: 4..5, value: Str( - "\n", + StringConstant { + value: "\n", + implicit_concatenated: false, + }, ), kind: None, }, @@ -35,6 +38,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap index 3d25aecfaef1f..8017bb4b3593b 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..9, value: Str( - "\u{88}", + StringConstant { + value: "\u{88}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap index 5212d6292e8f7..8680272f60834 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap @@ -6,20 +6,24 @@ expression: parse_ast Expr( StmtExpr { range: 0..17, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..17, values: [ Constant( ExprConstant { range: 1..16, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: None, }, ), ], + implicit_concatenated: true, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap index 5212d6292e8f7..8680272f60834 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap @@ -6,20 +6,24 @@ expression: parse_ast Expr( StmtExpr { range: 0..17, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..17, values: [ Constant( ExprConstant { range: 1..16, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: None, }, ), ], + implicit_concatenated: true, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap index f634b86a191c8..2c5e80aad5eff 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..22, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..22, values: [ Constant( ExprConstant { range: 1..16, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: None, }, @@ -26,7 +29,10 @@ expression: parse_ast ExprConstant { range: 17..20, value: Str( - "!", + StringConstant { + value: "!", + implicit_concatenated: false, + }, ), kind: None, }, @@ -37,6 +43,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: true, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap new file mode 100644 index 0000000000000..19e8b7ae045d7 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_4.snap @@ -0,0 +1,63 @@ +--- +source: crates/ruff_python_parser/src/string.rs +expression: parse_ast +--- +[ + Expr( + StmtExpr { + range: 0..31, + value: FString( + ExprFString { + range: 0..31, + values: [ + Constant( + ExprConstant { + range: 1..16, + value: Str( + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, + ), + kind: None, + }, + ), + FormattedValue( + ExprFormattedValue { + range: 16..21, + value: Constant( + ExprConstant { + range: 17..20, + value: Str( + StringConstant { + value: "!", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + Constant( + ExprConstant { + range: 24..30, + value: Str( + StringConstant { + value: "again!", + implicit_concatenated: true, + }, + ), + kind: None, + }, + ), + ], + implicit_concatenated: true, + }, + ), + }, + ), +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap index 12a39ccb923b2..282eb79f97d88 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap @@ -37,7 +37,10 @@ expression: parse_ast ExprConstant { range: 10..17, value: Str( - "{foo}", + StringConstant { + value: "{foo}", + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap new file mode 100644 index 0000000000000..97525a5e10db8 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_concatenation_string_spec.snap @@ -0,0 +1,50 @@ +--- +source: crates/ruff_python_parser/src/string.rs +expression: parse_ast +--- +[ + FormattedValue( + ExprFormattedValue { + range: 2..15, + value: Name( + ExprName { + range: 3..6, + id: "foo", + ctx: Load, + }, + ), + debug_text: None, + conversion: None, + format_spec: Some( + FString( + ExprFString { + range: 7..14, + values: [ + FormattedValue( + ExprFormattedValue { + range: 7..14, + value: Constant( + ExprConstant { + range: 8..13, + value: Str( + StringConstant { + value: "", + implicit_concatenated: true, + }, + ), + kind: None, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ), + }, + ), +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap index b88ece733182f..d93be4602f04e 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap @@ -16,8 +16,8 @@ expression: parse_ast debug_text: None, conversion: None, format_spec: Some( - JoinedStr( - ExprJoinedStr { + FString( + ExprFString { range: 7..13, values: [ FormattedValue( @@ -36,6 +36,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap new file mode 100644 index 0000000000000..31db5e6cf8997 --- /dev/null +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_string_spec.snap @@ -0,0 +1,50 @@ +--- +source: crates/ruff_python_parser/src/string.rs +expression: parse_ast +--- +[ + FormattedValue( + ExprFormattedValue { + range: 2..12, + value: Name( + ExprName { + range: 3..6, + id: "foo", + ctx: Load, + }, + ), + debug_text: None, + conversion: None, + format_spec: Some( + FString( + ExprFString { + range: 7..11, + values: [ + FormattedValue( + ExprFormattedValue { + range: 7..11, + value: Constant( + ExprConstant { + range: 8..10, + value: Str( + StringConstant { + value: "", + implicit_concatenated: false, + }, + ), + kind: None, + }, + ), + debug_text: None, + conversion: None, + format_spec: None, + }, + ), + ], + implicit_concatenated: false, + }, + ), + ), + }, + ), +] diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap index 98f2635d010d7..5a621fc857611 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap @@ -16,20 +16,24 @@ expression: parse_ast debug_text: None, conversion: None, format_spec: Some( - JoinedStr( - ExprJoinedStr { + FString( + ExprFString { range: 7..11, values: [ Constant( ExprConstant { range: 7..11, value: Str( - "spec", + StringConstant { + value: "spec", + implicit_concatenated: false, + }, ), kind: None, }, ), ], + implicit_concatenated: false, }, ), ), diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap index 68f419ced0a40..2c5d32050d5c0 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..16, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap index b6561e362d72b..8e2e003f917ab 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..20, value: Str( - "Hello, world!", + StringConstant { + value: "Hello, world!", + implicit_concatenated: false, + }, ), kind: Some( "u", diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap index 51f75d9b69b10..23593fee07d09 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..18, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..18, values: [ Constant( ExprConstant { range: 2..17, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: Some( "u", @@ -22,6 +25,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: true, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap index 30f7c37ff0b65..e6a8a74995440 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap @@ -6,15 +6,18 @@ expression: parse_ast Expr( StmtExpr { range: 0..22, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..22, values: [ Constant( ExprConstant { range: 2..21, value: Str( - "Hello world!", + StringConstant { + value: "Hello world!", + implicit_concatenated: true, + }, ), kind: Some( "u", @@ -22,6 +25,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: true, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap index 629c241e8ea2a..cb8d2848a9613 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..17, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap index f89a6bd7f7141..6fdde47ad2c56 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap @@ -10,7 +10,10 @@ expression: parse_ast ExprConstant { range: 0..17, value: Str( - "Hello world", + StringConstant { + value: "Hello world", + implicit_concatenated: true, + }, ), kind: Some( "u", diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap index 55f2380f023aa..37273bc676714 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap @@ -10,12 +10,15 @@ expression: parse_ast ExprConstant { range: 0..8, value: Bytes( - [ - 92, - 120, - 49, - 122, - ], + BytesConstant { + value: [ + 92, + 120, + 49, + 122, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap index 8a44d4ee8f82f..558aae8c958f5 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap @@ -10,10 +10,13 @@ expression: parse_ast ExprConstant { range: 0..6, value: Bytes( - [ - 92, - 92, - ], + BytesConstant { + value: [ + 92, + 92, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap index 6fcffbfb92523..65f4daf83d8d7 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap @@ -6,8 +6,8 @@ expression: parse_ast Expr( StmtExpr { range: 0..7, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..7, values: [ FormattedValue( @@ -26,6 +26,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap index 1b6f47e27aff9..7ec79b41ff8ff 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap @@ -10,264 +10,267 @@ expression: parse_ast ExprConstant { range: 0..738, value: Bytes( - [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100, - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120, - 121, - 122, - 123, - 124, - 125, - 126, - 127, - 128, - 129, - 130, - 131, - 132, - 133, - 134, - 135, - 136, - 137, - 138, - 139, - 140, - 141, - 142, - 143, - 144, - 145, - 146, - 147, - 148, - 149, - 150, - 151, - 152, - 153, - 154, - 155, - 156, - 157, - 158, - 159, - 160, - 161, - 162, - 163, - 164, - 165, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 174, - 175, - 176, - 177, - 178, - 179, - 180, - 181, - 182, - 183, - 184, - 185, - 186, - 187, - 188, - 189, - 190, - 191, - 192, - 193, - 194, - 195, - 196, - 197, - 198, - 199, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 209, - 210, - 211, - 212, - 213, - 214, - 215, - 216, - 217, - 218, - 219, - 220, - 221, - 222, - 223, - 224, - 225, - 226, - 227, - 228, - 229, - 230, - 231, - 232, - 233, - 234, - 235, - 236, - 237, - 238, - 239, - 240, - 241, - 242, - 243, - 244, - 245, - 246, - 247, - 248, - 249, - 250, - 251, - 252, - 253, - 254, - 255, - ], + BytesConstant { + value: [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + ], + implicit_concatenated: false, + }, ), kind: None, }, diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap index 410327f96917a..6793e65f73804 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap @@ -6,8 +6,8 @@ expression: parse_ast Expr( StmtExpr { range: 0..11, - value: JoinedStr( - ExprJoinedStr { + value: FString( + ExprFString { range: 0..11, values: [ FormattedValue( @@ -26,6 +26,7 @@ expression: parse_ast }, ), ], + implicit_concatenated: false, }, ), }, diff --git a/crates/ruff_python_parser/src/soft_keywords.rs b/crates/ruff_python_parser/src/soft_keywords.rs index eaf3804b8cfac..f7aab9c1137a6 100644 --- a/crates/ruff_python_parser/src/soft_keywords.rs +++ b/crates/ruff_python_parser/src/soft_keywords.rs @@ -132,8 +132,8 @@ where } } - self.start_of_line = next.as_ref().map_or(false, |lex_result| { - lex_result.as_ref().map_or(false, |(tok, _)| { + self.start_of_line = next.as_ref().is_some_and(|lex_result| { + lex_result.as_ref().is_ok_and(|(tok, _)| { if matches!(tok, Tok::NonLogicalNewline | Tok::Comment { .. }) { return self.start_of_line; } diff --git a/crates/ruff_python_parser/src/string.rs b/crates/ruff_python_parser/src/string.rs index 5d212c3a457ad..beeb5b9dc0942 100644 --- a/crates/ruff_python_parser/src/string.rs +++ b/crates/ruff_python_parser/src/string.rs @@ -1,6 +1,4 @@ -use itertools::Itertools; - -use ruff_python_ast::{self as ast, Constant, Expr}; +use ruff_python_ast::{self as ast, BytesConstant, Constant, Expr, StringConstant}; use ruff_python_ast::{ConversionFlag, Ranged}; use ruff_text_size::{TextLen, TextRange, TextSize}; @@ -11,9 +9,9 @@ use ruff_text_size::{TextLen, TextRange, TextSize}; // we have to do the parsing here, manually. use crate::{ lexer::{LexicalError, LexicalErrorType}, + parse_expression_starts_at, parser::{ParseError, ParseErrorType}, token::{StringKind, Tok}, - Parse, }; // unicode_name2 does not expose `MAX_NAME_LENGTH`, so we replicate that constant here, fix #3798 @@ -243,8 +241,9 @@ impl<'a> StringParser<'a> { let start_location = self.get_pos(); let parsed_spec = self.parse_spec(nested)?; - spec = Some(Box::new(Expr::from(ast::ExprJoinedStr { + spec = Some(Box::new(Expr::from(ast::ExprFString { values: parsed_spec, + implicit_concatenated: false, range: self.range(start_location), }))); } @@ -319,9 +318,8 @@ impl<'a> StringParser<'a> { ) })?; let leading = - &expression[..usize::from(value.range().start() - start_location) - 1]; - let trailing = - &expression[usize::from(value.range().end() - start_location) - 1..]; + &expression[..usize::from(value.start() - start_location) - 1]; + let trailing = &expression[usize::from(value.end() - start_location) - 1..]; vec![Expr::from(ast::ExprFormattedValue { value: Box::new(value), debug_text: Some(ast::DebugText { @@ -387,7 +385,7 @@ impl<'a> StringParser<'a> { '{' => { if !constant_piece.is_empty() { spec_constructor.push(Expr::from(ast::ExprConstant { - value: constant_piece.drain(..).collect::().into(), + value: std::mem::take(&mut constant_piece).into(), kind: None, range: self.range(start_location), })); @@ -408,7 +406,7 @@ impl<'a> StringParser<'a> { } if !constant_piece.is_empty() { spec_constructor.push(Expr::from(ast::ExprConstant { - value: constant_piece.drain(..).collect::().into(), + value: std::mem::take(&mut constant_piece).into(), kind: None, range: self.range(start_location), })); @@ -446,7 +444,7 @@ impl<'a> StringParser<'a> { } if !content.is_empty() { values.push(Expr::from(ast::ExprConstant { - value: content.drain(..).collect::().into(), + value: std::mem::take(&mut content).into(), kind: None, range: self.range(start_location), })); @@ -513,25 +511,25 @@ impl<'a> StringParser<'a> { } Ok(Expr::from(ast::ExprConstant { - value: Constant::Bytes(content.chars().map(|c| c as u8).collect()), + value: content.chars().map(|c| c as u8).collect::>().into(), kind: None, range: self.range(start_location), })) } fn parse_string(&mut self) -> Result { - let mut content = String::new(); + let mut value = String::new(); let start_location = self.get_pos(); while let Some(ch) = self.next_char() { match ch { '\\' if !self.kind.is_raw() => { - content.push_str(&self.parse_escaped_char()?); + value.push_str(&self.parse_escaped_char()?); } - ch => content.push(ch), + ch => value.push(ch), } } Ok(Expr::from(ast::ExprConstant { - value: Constant::Str(content), + value: value.into(), kind: self.kind.is_unicode().then(|| "u".to_string()), range: self.range(start_location), })) @@ -550,7 +548,7 @@ impl<'a> StringParser<'a> { fn parse_fstring_expr(source: &str, location: TextSize) -> Result { let fstring_body = format!("({source})"); - ast::Expr::parse_starts_at(&fstring_body, "", location) + parse_expression_starts_at(&fstring_body, "", location) } fn parse_string( @@ -577,6 +575,7 @@ pub(crate) fn parse_strings( .filter(|(_, (_, kind, ..), _)| kind.is_any_bytes()) .count(); let has_bytes = num_bytes > 0; + let implicit_concatenated = values.len() > 1; if has_bytes && num_bytes < values.len() { return Err(LexicalError { @@ -593,7 +592,7 @@ pub(crate) fn parse_strings( for value in parse_string(&source, kind, triple_quoted, start)? { match value { Expr::Constant(ast::ExprConstant { - value: Constant::Bytes(value), + value: Constant::Bytes(BytesConstant { value, .. }), .. }) => content.extend(value), _ => unreachable!("Unexpected non-bytes expression."), @@ -601,7 +600,10 @@ pub(crate) fn parse_strings( } } return Ok(ast::ExprConstant { - value: Constant::Bytes(content), + value: Constant::Bytes(BytesConstant { + value: content, + implicit_concatenated, + }), kind: None, range: TextRange::new(initial_start, last_end), } @@ -614,7 +616,7 @@ pub(crate) fn parse_strings( for value in parse_string(&source, kind, triple_quoted, start)? { match value { Expr::Constant(ast::ExprConstant { - value: Constant::Str(value), + value: Constant::Str(StringConstant { value, .. }), .. }) => content.push(value), _ => unreachable!("Unexpected non-string expression."), @@ -622,7 +624,10 @@ pub(crate) fn parse_strings( } } return Ok(ast::ExprConstant { - value: Constant::Str(content.join("")), + value: Constant::Str(StringConstant { + value: content.join(""), + implicit_concatenated, + }), kind: initial_kind, range: TextRange::new(initial_start, last_end), } @@ -637,7 +642,10 @@ pub(crate) fn parse_strings( let take_current = |current: &mut Vec, start, end| -> Expr { Expr::Constant(ast::ExprConstant { - value: Constant::Str(current.drain(..).join("")), + value: Constant::Str(StringConstant { + value: current.drain(..).collect::(), + implicit_concatenated, + }), kind: initial_kind.clone(), range: TextRange::new(start, end), }) @@ -654,14 +662,14 @@ pub(crate) fn parse_strings( deduped.push(value); } Expr::Constant(ast::ExprConstant { - value: Constant::Str(inner), + value: Constant::Str(StringConstant { value, .. }), .. }) => { if current.is_empty() { current_start = value_range.start(); } current_end = value_range.end(); - current.push(inner); + current.push(value); } _ => unreachable!("Unexpected non-string expression."), } @@ -671,8 +679,9 @@ pub(crate) fn parse_strings( deduped.push(take_current(&mut current, current_start, current_end)); } - Ok(Expr::JoinedStr(ast::ExprJoinedStr { + Ok(Expr::FString(ast::ExprFString { values: deduped, + implicit_concatenated, range: TextRange::new(initial_start, last_end), })) } @@ -785,10 +794,8 @@ impl From for crate::parser::LalrpopError Result, LexicalError> { StringParser::new(source, StringKind::FString, false, TextSize::default()).parse() @@ -926,63 +933,70 @@ mod tests { #[test] fn test_parse_string_concat() { let source = "'Hello ' 'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_u_string_concat_1() { let source = "'Hello ' u'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_u_string_concat_2() { let source = "u'Hello ' 'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_f_string_concat_1() { let source = "'Hello ' f'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_f_string_concat_2() { let source = "'Hello ' f'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_f_string_concat_3() { let source = "'Hello ' f'world{\"!\"}'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } + + #[test] + fn test_parse_f_string_concat_4() { + let source = "'Hello ' f'world{\"!\"}' 'again!'"; + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_u_f_string_concat_1() { let source = "u'Hello ' f'world'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_u_f_string_concat_2() { let source = "u'Hello ' f'world' '!'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_parse_string_triple_quotes_with_kind() { let source = "u'''Hello, world!'''"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -990,7 +1004,7 @@ mod tests { fn test_single_quoted_byte() { // single quote let source = r##"b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'"##; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -998,50 +1012,50 @@ mod tests { fn test_double_quoted_byte() { // double quote let source = r##"b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff""##; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_escape_char_in_byte_literal() { // backslash does not escape - let source = r##"b"omkmok\Xaa""##; // spell-checker:ignore omkmok - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let source = r#"b"omkmok\Xaa""#; // spell-checker:ignore omkmok + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_raw_byte_literal_1() { let source = r"rb'\x1z'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_raw_byte_literal_2() { let source = r"rb'\\'"; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_escape_octet() { - let source = r##"b'\43a\4\1234'"##; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let source = r"b'\43a\4\1234'"; + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_fstring_escaped_newline() { let source = r#"f"\n{x}""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_fstring_constant_range() { let source = r#"f"aaa{bbb}ccc{ddd}eee""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -1049,28 +1063,28 @@ mod tests { fn test_fstring_unescaped_newline() { let source = r#"f""" {x}""""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_fstring_escaped_character() { let source = r#"f"\\{x}""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_raw_fstring() { let source = r#"rf"{x}""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } #[test] fn test_triple_quoted_raw_fstring() { let source = r#"rf"""{x}""""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } @@ -1078,7 +1092,23 @@ mod tests { fn test_fstring_line_continuation() { let source = r#"rf"\ {x}""#; - let parse_ast = ast::Suite::parse(source, "").unwrap(); + let parse_ast = parse_suite(source, "").unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } + + #[test] + fn test_parse_fstring_nested_string_spec() { + let source = "{foo:{''}}"; + let parse_ast = parse_fstring(source).unwrap(); + + insta::assert_debug_snapshot!(parse_ast); + } + + #[test] + fn test_parse_fstring_nested_concatenation_string_spec() { + let source = "{foo:{'' ''}}"; + let parse_ast = parse_fstring(source).unwrap(); + insta::assert_debug_snapshot!(parse_ast); } @@ -1088,7 +1118,7 @@ mod tests { #[test] fn $name() { let source = format!(r#""\N{{{0}}}""#, $alias); - let parse_ast = ast::Suite::parse(&source, "").unwrap(); + let parse_ast = parse_suite(&source, "").unwrap(); insta::assert_debug_snapshot!(parse_ast); } )* diff --git a/crates/ruff_python_parser/src/token.rs b/crates/ruff_python_parser/src/token.rs index 526081ac26817..db159a0340e03 100644 --- a/crates/ruff_python_parser/src/token.rs +++ b/crates/ruff_python_parser/src/token.rs @@ -6,7 +6,7 @@ //! [CPython source]: https://github.com/python/cpython/blob/dfc2e065a2e71011017077e549cd2f9bf4944c54/Include/internal/pycore_token.h; use crate::Mode; use num_bigint::BigInt; -use ruff_python_ast::MagicKind; +use ruff_python_ast::IpyEscapeKind; use ruff_text_size::TextSize; use std::fmt; @@ -44,13 +44,13 @@ pub enum Tok { /// Whether the string is triple quoted. triple_quoted: bool, }, - /// Token value for a Jupyter magic commands. These are filtered out of the token stream - /// prior to parsing when the mode is [`Mode::Jupyter`]. - MagicCommand { + /// Token value for IPython escape commands. These are recognized by the lexer + /// only when the mode is [`Mode::Jupyter`]. + IpyEscapeCommand { /// The magic command value. value: String, /// The kind of magic command. - kind: MagicKind, + kind: IpyEscapeKind, }, /// Token value for a comment. These are filtered out of the token stream prior to parsing. Comment(String), @@ -64,6 +64,8 @@ pub enum Tok { /// Token value for a dedent. Dedent, EndOfFile, + /// Token value for a question mark `?`. This is only used in [`Mode::Jupyter`]. + Question, /// Token value for a left parenthesis `(`. Lpar, /// Token value for a right parenthesis `)`. @@ -232,7 +234,7 @@ impl fmt::Display for Tok { let quotes = "\"".repeat(if *triple_quoted { 3 } else { 1 }); write!(f, "{kind}{quotes}{value}{quotes}") } - MagicCommand { kind, value } => write!(f, "{kind}{value}"), + IpyEscapeCommand { kind, value } => write!(f, "{kind}{value}"), Newline => f.write_str("Newline"), NonLogicalNewline => f.write_str("NonLogicalNewline"), Indent => f.write_str("Indent"), @@ -240,6 +242,7 @@ impl fmt::Display for Tok { StartModule => f.write_str("StartProgram"), StartExpression => f.write_str("StartExpression"), EndOfFile => f.write_str("EOF"), + Question => f.write_str("'?'"), Lpar => f.write_str("'('"), Rpar => f.write_str("')'"), Lsqb => f.write_str("'['"), @@ -447,8 +450,8 @@ pub enum TokenKind { Complex, /// Token value for a string. String, - /// Token value for a Jupyter magic command. - MagicCommand, + /// Token value for a IPython escape command. + EscapeCommand, /// Token value for a comment. These are filtered out of the token stream prior to parsing. Comment, /// Token value for a newline. @@ -461,6 +464,8 @@ pub enum TokenKind { /// Token value for a dedent. Dedent, EndOfFile, + /// Token value for a question mark `?`. + Question, /// Token value for a left parenthesis `(`. Lpar, /// Token value for a right parenthesis `)`. @@ -776,13 +781,14 @@ impl TokenKind { Tok::Float { .. } => TokenKind::Float, Tok::Complex { .. } => TokenKind::Complex, Tok::String { .. } => TokenKind::String, - Tok::MagicCommand { .. } => TokenKind::MagicCommand, + Tok::IpyEscapeCommand { .. } => TokenKind::EscapeCommand, Tok::Comment(_) => TokenKind::Comment, Tok::Newline => TokenKind::Newline, Tok::NonLogicalNewline => TokenKind::NonLogicalNewline, Tok::Indent => TokenKind::Indent, Tok::Dedent => TokenKind::Dedent, Tok::EndOfFile => TokenKind::EndOfFile, + Tok::Question => TokenKind::Question, Tok::Lpar => TokenKind::Lpar, Tok::Rpar => TokenKind::Rpar, Tok::Lsqb => TokenKind::Lsqb, diff --git a/crates/ruff_python_parser/src/typing.rs b/crates/ruff_python_parser/src/typing.rs index 075da24419aac..d9c25e5e9480b 100644 --- a/crates/ruff_python_parser/src/typing.rs +++ b/crates/ruff_python_parser/src/typing.rs @@ -1,4 +1,4 @@ -use crate::Parse; +use crate::{parse_expression, parse_expression_starts_at}; use anyhow::Result; use ruff_python_ast::relocate::relocate_expr; use ruff_python_ast::str; @@ -27,13 +27,13 @@ pub fn parse_type_annotation( ) -> Result<(Expr, AnnotationKind)> { let expression = &source[range]; - if str::raw_contents(expression).map_or(false, |body| body == value) { + if str::raw_contents(expression).is_some_and(|body| body == value) { // The annotation is considered "simple" if and only if the raw representation (e.g., // `List[int]` within "List[int]") exactly matches the parsed representation. This // isn't the case, e.g., for implicit concatenations, or for annotations that contain // escaped quotes. let leading_quote = str::leading_quote(expression).unwrap(); - let expr = Expr::parse_starts_at( + let expr = parse_expression_starts_at( value, "", range.start() + leading_quote.text_len(), @@ -41,7 +41,7 @@ pub fn parse_type_annotation( Ok((expr, AnnotationKind::Simple)) } else { // Otherwise, consider this a "complex" annotation. - let mut expr = Expr::parse(value, "")?; + let mut expr = parse_expression(value, "")?; relocate_expr(&mut expr, range); Ok((expr, AnnotationKind::Complex)) } diff --git a/crates/ruff_python_resolver/src/native_module.rs b/crates/ruff_python_resolver/src/native_module.rs index 065473d6a5f57..fe4f41276aa23 100644 --- a/crates/ruff_python_resolver/src/native_module.rs +++ b/crates/ruff_python_resolver/src/native_module.rs @@ -28,7 +28,7 @@ pub(crate) fn is_native_module_file_name(module_name: &str, file_name: &Path) -> // The file name must be that of a native module. if !file_name .extension() - .map_or(false, is_native_module_file_extension) + .is_some_and(is_native_module_file_extension) { return false; }; @@ -45,7 +45,7 @@ pub(crate) fn find_native_module( Ok(dir_path .read_dir()? .flatten() - .filter(|entry| entry.file_type().map_or(false, |ft| ft.is_file())) + .filter(|entry| entry.file_type().is_ok_and(|ft| ft.is_file())) .map(|entry| entry.path()) .find(|path| is_native_module_file_name(module_name, path))) } diff --git a/crates/ruff_python_resolver/src/resolver.rs b/crates/ruff_python_resolver/src/resolver.rs index 2ea16acca4743..7bbab3535f6ab 100644 --- a/crates/ruff_python_resolver/src/resolver.rs +++ b/crates/ruff_python_resolver/src/resolver.rs @@ -292,7 +292,7 @@ fn resolve_best_absolute_import( && typings_import .resolved_paths .last() - .map_or(false, |path| path.as_os_str().is_empty()) + .is_some_and(|path| path.as_os_str().is_empty()) { if typings_import .implicit_imports @@ -381,9 +381,10 @@ fn resolve_best_absolute_import( typeshed_root.display() ); if typeshed_root != execution_environment.root { - if best_result_so_far.as_ref().map_or(false, |result| { - result.py_typed_info.is_some() && !result.is_partly_resolved - }) { + if best_result_so_far + .as_ref() + .is_some_and(|result| result.py_typed_info.is_some() && !result.is_partly_resolved) + { return best_result_so_far; } } diff --git a/crates/ruff_python_resolver/src/search.rs b/crates/ruff_python_resolver/src/search.rs index 0539c8296a098..83eb9d4f3a177 100644 --- a/crates/ruff_python_resolver/src/search.rs +++ b/crates/ruff_python_resolver/src/search.rs @@ -81,7 +81,7 @@ fn find_site_packages_path( if let Some(preferred_dir) = candidate_dirs.iter().find(|dir| { dir.file_name() .and_then(OsStr::to_str) - .map_or(false, |name| name == python_version.dir()) + .is_some_and(|name| name == python_version.dir()) }) { debug!("Found path `{}`", preferred_dir.display()); return Some(preferred_dir.join(SITE_PACKAGES)); @@ -235,7 +235,7 @@ fn build_typeshed_third_party_package_map( if inner_entry .path() .extension() - .map_or(false, |extension| extension == "pyi") + .is_some_and(|extension| extension == "pyi") { if let Some(stripped_file_name) = inner_entry .path() diff --git a/crates/ruff_python_semantic/Cargo.toml b/crates/ruff_python_semantic/Cargo.toml index 9b37767711b83..58484d140d24b 100644 --- a/crates/ruff_python_semantic/Cargo.toml +++ b/crates/ruff_python_semantic/Cargo.toml @@ -23,6 +23,7 @@ bitflags = { workspace = true } is-macro = { workspace = true } num-traits = { workspace = true } rustc-hash = { workspace = true } - - smallvec = { workspace = true } + +[dev-dependencies] +ruff_python_parser = { path = "../ruff_python_parser" } diff --git a/crates/ruff_python_semantic/src/analyze/branch_detection.rs b/crates/ruff_python_semantic/src/analyze/branch_detection.rs deleted file mode 100644 index 64ac31e80fb88..0000000000000 --- a/crates/ruff_python_semantic/src/analyze/branch_detection.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::cmp::Ordering; -use std::iter; - -use ruff_python_ast::{self as ast, ExceptHandler, Stmt}; - -use crate::node::{NodeId, Nodes}; - -/// Return the common ancestor of `left` and `right` below `stop`, or `None`. -fn common_ancestor( - left: NodeId, - right: NodeId, - stop: Option, - node_tree: &Nodes, -) -> Option { - if stop.map_or(false, |stop| left == stop || right == stop) { - return None; - } - - if left == right { - return Some(left); - } - - let left_depth = node_tree.depth(left); - let right_depth = node_tree.depth(right); - - match left_depth.cmp(&right_depth) { - Ordering::Less => { - let right = node_tree.parent_id(right)?; - common_ancestor(left, right, stop, node_tree) - } - Ordering::Equal => { - let left = node_tree.parent_id(left)?; - let right = node_tree.parent_id(right)?; - common_ancestor(left, right, stop, node_tree) - } - Ordering::Greater => { - let left = node_tree.parent_id(left)?; - common_ancestor(left, right, stop, node_tree) - } - } -} - -/// Return the alternative branches for a given node. -fn alternatives(stmt: &Stmt) -> Vec> { - match stmt { - Stmt::If(ast::StmtIf { - body, - elif_else_clauses, - .. - }) => iter::once(body.iter().collect()) - .chain( - elif_else_clauses - .iter() - .map(|clause| clause.body.iter().collect()), - ) - .collect(), - Stmt::Try(ast::StmtTry { - body, - handlers, - orelse, - .. - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - .. - }) => vec![body.iter().chain(orelse.iter()).collect()] - .into_iter() - .chain(handlers.iter().map(|handler| { - let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { body, .. }) = - handler; - body.iter().collect() - })) - .collect(), - Stmt::Match(ast::StmtMatch { cases, .. }) => cases - .iter() - .map(|case| case.body.iter().collect()) - .collect(), - _ => vec![], - } -} - -/// Return `true` if `stmt` is a descendent of any of the nodes in `ancestors`. -fn descendant_of<'a>( - stmt: NodeId, - ancestors: &[&'a Stmt], - stop: NodeId, - node_tree: &Nodes<'a>, -) -> bool { - ancestors.iter().any(|ancestor| { - node_tree.node_id(ancestor).map_or(false, |ancestor| { - common_ancestor(stmt, ancestor, Some(stop), node_tree).is_some() - }) - }) -} - -/// Return `true` if `left` and `right` are on different branches of an `if` or -/// `try` statement. -pub fn different_forks(left: NodeId, right: NodeId, node_tree: &Nodes) -> bool { - if let Some(ancestor) = common_ancestor(left, right, None, node_tree) { - for items in alternatives(node_tree[ancestor]) { - let l = descendant_of(left, &items, ancestor, node_tree); - let r = descendant_of(right, &items, ancestor, node_tree); - if l ^ r { - return true; - } - } - } - false -} diff --git a/crates/ruff_python_semantic/src/analyze/function_type.rs b/crates/ruff_python_semantic/src/analyze/function_type.rs index 7cf4884716b12..8289eb26fd68c 100644 --- a/crates/ruff_python_semantic/src/analyze/function_type.rs +++ b/crates/ruff_python_semantic/src/analyze/function_type.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::Decorator; - use ruff_python_ast::call_path::from_qualified_name; use ruff_python_ast::helpers::map_callable; +use ruff_python_ast::Decorator; use crate::model::SemanticModel; use crate::scope::{Scope, ScopeKind}; @@ -23,7 +22,7 @@ pub fn classify( classmethod_decorators: &[String], staticmethod_decorators: &[String], ) -> FunctionType { - let ScopeKind::Class(scope) = &scope.kind else { + let ScopeKind::Class(class_def) = &scope.kind else { return FunctionType::Function; }; if decorator_list.iter().any(|decorator| { @@ -31,7 +30,7 @@ pub fn classify( // `@staticmethod`). semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["", "staticmethod"] | ["abc", "abstractstaticmethod"] @@ -43,11 +42,11 @@ pub fn classify( FunctionType::StaticMethod } else if matches!(name, "__new__" | "__init_subclass__" | "__class_getitem__") // Special-case class method, like `__new__`. - || scope.bases.iter().any(|expr| { + || class_def.bases().iter().any(|expr| { // The class itself extends a known metaclass, so all methods are class methods. semantic .resolve_call_path(map_callable(expr)) - .map_or(false, |call_path| { + .is_some_and( |call_path| { matches!(call_path.as_slice(), ["", "type"] | ["abc", "ABCMeta"]) }) }) @@ -55,7 +54,7 @@ pub fn classify( // The method is decorated with a class method decorator (like `@classmethod`). semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { + .is_some_and( |call_path| { matches!( call_path.as_slice(), ["", "classmethod"] | ["abc", "abstractclassmethod"] diff --git a/crates/ruff_python_semantic/src/analyze/logging.rs b/crates/ruff_python_semantic/src/analyze/logging.rs index fa5006519f6b1..205e3bb8e4c3b 100644 --- a/crates/ruff_python_semantic/src/analyze/logging.rs +++ b/crates/ruff_python_semantic/src/analyze/logging.rs @@ -1,7 +1,6 @@ -use ruff_python_ast::{self as ast, Expr, Keyword}; - use ruff_python_ast::call_path::{collect_call_path, from_qualified_name}; -use ruff_python_ast::helpers::{find_keyword, is_const_true}; +use ruff_python_ast::helpers::is_const_true; +use ruff_python_ast::{self as ast, Arguments, Expr, Keyword}; use crate::model::SemanticModel; @@ -50,7 +49,13 @@ pub fn is_logger_candidate( // logger names. if let Some(call_path) = collect_call_path(value) { if let Some(tail) = call_path.last() { - if tail.starts_with("log") || tail.ends_with("logger") || tail.ends_with("logging") { + if tail.starts_with("log") + || tail.ends_with("logger") + || tail.ends_with("logging") + || tail.starts_with("LOG") + || tail.ends_with("LOGGER") + || tail.ends_with("LOGGING") + { return true; } } @@ -61,8 +66,8 @@ pub fn is_logger_candidate( /// If the keywords to a logging call contain `exc_info=True` or `exc_info=sys.exc_info()`, /// return the `Keyword` for `exc_info`. -pub fn exc_info<'a>(keywords: &'a [Keyword], semantic: &SemanticModel) -> Option<&'a Keyword> { - let exc_info = find_keyword(keywords, "exc_info")?; +pub fn exc_info<'a>(arguments: &'a Arguments, semantic: &SemanticModel) -> Option<&'a Keyword> { + let exc_info = arguments.find_keyword("exc_info")?; // Ex) `logging.error("...", exc_info=True)` if is_const_true(&exc_info.value) { @@ -74,9 +79,7 @@ pub fn exc_info<'a>(keywords: &'a [Keyword], semantic: &SemanticModel) -> Option .value .as_call_expr() .and_then(|call| semantic.resolve_call_path(&call.func)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["sys", "exc_info"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["sys", "exc_info"])) { return Some(exc_info); } diff --git a/crates/ruff_python_semantic/src/analyze/mod.rs b/crates/ruff_python_semantic/src/analyze/mod.rs index f8cb0664802c6..941309a526c26 100644 --- a/crates/ruff_python_semantic/src/analyze/mod.rs +++ b/crates/ruff_python_semantic/src/analyze/mod.rs @@ -1,4 +1,3 @@ -pub mod branch_detection; pub mod function_type; pub mod logging; pub mod type_inference; diff --git a/crates/ruff_python_semantic/src/analyze/type_inference.rs b/crates/ruff_python_semantic/src/analyze/type_inference.rs index d65b544b2a34c..4bba5b9826010 100644 --- a/crates/ruff_python_semantic/src/analyze/type_inference.rs +++ b/crates/ruff_python_semantic/src/analyze/type_inference.rs @@ -1,7 +1,317 @@ //! Analysis rules to perform basic type inference on individual expressions. +use rustc_hash::FxHashSet; + use ruff_python_ast as ast; -use ruff_python_ast::{Constant, Expr}; +use ruff_python_ast::{Constant, Expr, Operator, UnaryOp}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ResolvedPythonType { + /// The expression resolved to a single known type, like `str` or `int`. + Atom(PythonType), + /// The expression resolved to a union of known types, like `str | int`. + Union(FxHashSet), + /// The expression resolved to an unknown type, like a variable or function call. + Unknown, + /// The expression resolved to a `TypeError`, like `1 + "hello"`. + TypeError, +} + +impl ResolvedPythonType { + #[must_use] + pub fn union(self, other: Self) -> Self { + match (self, other) { + (Self::TypeError, _) | (_, Self::TypeError) => Self::TypeError, + (Self::Unknown, _) | (_, Self::Unknown) => Self::Unknown, + (Self::Atom(a), Self::Atom(b)) => { + if a == b { + Self::Atom(a) + } else { + Self::Union(FxHashSet::from_iter([a, b])) + } + } + (Self::Atom(a), Self::Union(mut b)) => { + b.insert(a); + Self::Union(b) + } + (Self::Union(mut a), Self::Atom(b)) => { + a.insert(b); + Self::Union(a) + } + (Self::Union(mut a), Self::Union(b)) => { + a.extend(b); + Self::Union(a) + } + } + } +} + +impl From<&Expr> for ResolvedPythonType { + fn from(expr: &Expr) -> Self { + match expr { + // Primitives. + Expr::Dict(_) => ResolvedPythonType::Atom(PythonType::Dict), + Expr::DictComp(_) => ResolvedPythonType::Atom(PythonType::Dict), + Expr::Set(_) => ResolvedPythonType::Atom(PythonType::Set), + Expr::SetComp(_) => ResolvedPythonType::Atom(PythonType::Set), + Expr::List(_) => ResolvedPythonType::Atom(PythonType::List), + Expr::ListComp(_) => ResolvedPythonType::Atom(PythonType::List), + Expr::Tuple(_) => ResolvedPythonType::Atom(PythonType::Tuple), + Expr::GeneratorExp(_) => ResolvedPythonType::Atom(PythonType::Generator), + Expr::FString(_) => ResolvedPythonType::Atom(PythonType::String), + Expr::Constant(ast::ExprConstant { value, .. }) => match value { + Constant::Str(_) => ResolvedPythonType::Atom(PythonType::String), + Constant::Int(_) => { + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + } + Constant::Float(_) => { + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + } + Constant::Bool(_) => ResolvedPythonType::Atom(PythonType::Number(NumberLike::Bool)), + Constant::Complex { .. } => { + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Complex)) + } + Constant::None => ResolvedPythonType::Atom(PythonType::None), + Constant::Ellipsis => ResolvedPythonType::Atom(PythonType::Ellipsis), + Constant::Bytes(_) => ResolvedPythonType::Atom(PythonType::Bytes), + }, + // Simple container expressions. + Expr::NamedExpr(ast::ExprNamedExpr { value, .. }) => { + ResolvedPythonType::from(value.as_ref()) + } + Expr::IfExp(ast::ExprIfExp { body, orelse, .. }) => { + let body = ResolvedPythonType::from(body.as_ref()); + let orelse = ResolvedPythonType::from(orelse.as_ref()); + body.union(orelse) + } + + // Boolean operators. + Expr::BoolOp(ast::ExprBoolOp { values, .. }) => values + .iter() + .map(ResolvedPythonType::from) + .reduce(ResolvedPythonType::union) + .unwrap_or(ResolvedPythonType::Unknown), + + // Unary operators. + Expr::UnaryOp(ast::ExprUnaryOp { operand, op, .. }) => match op { + UnaryOp::Invert => { + return match ResolvedPythonType::from(operand.as_ref()) { + ResolvedPythonType::Atom(PythonType::Number( + NumberLike::Bool | NumberLike::Integer, + )) => ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)), + ResolvedPythonType::Atom(_) => ResolvedPythonType::TypeError, + _ => ResolvedPythonType::Unknown, + } + } + // Ex) `not 1.0` + UnaryOp::Not => ResolvedPythonType::Atom(PythonType::Number(NumberLike::Bool)), + // Ex) `+1` or `-1` + UnaryOp::UAdd | UnaryOp::USub => { + return match ResolvedPythonType::from(operand.as_ref()) { + ResolvedPythonType::Atom(PythonType::Number(number)) => { + ResolvedPythonType::Atom(PythonType::Number( + if number == NumberLike::Bool { + NumberLike::Integer + } else { + number + }, + )) + } + ResolvedPythonType::Atom(_) => ResolvedPythonType::TypeError, + _ => ResolvedPythonType::Unknown, + } + } + }, + + // Binary operators. + Expr::BinOp(ast::ExprBinOp { + left, op, right, .. + }) => { + match op { + Operator::Add => { + match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `"Hello" + "world"` + ( + ResolvedPythonType::Atom(PythonType::String), + ResolvedPythonType::Atom(PythonType::String), + ) => return ResolvedPythonType::Atom(PythonType::String), + // Ex) `b"Hello" + b"world"` + ( + ResolvedPythonType::Atom(PythonType::Bytes), + ResolvedPythonType::Atom(PythonType::Bytes), + ) => return ResolvedPythonType::Atom(PythonType::Bytes), + // Ex) `[1] + [2]` + ( + ResolvedPythonType::Atom(PythonType::List), + ResolvedPythonType::Atom(PythonType::List), + ) => return ResolvedPythonType::Atom(PythonType::List), + // Ex) `(1, 2) + (3, 4)` + ( + ResolvedPythonType::Atom(PythonType::Tuple), + ResolvedPythonType::Atom(PythonType::Tuple), + ) => return ResolvedPythonType::Atom(PythonType::Tuple), + // Ex) `1 + 1.0` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + return ResolvedPythonType::Atom(PythonType::Number( + left.coerce(right), + )); + } + // Ex) `"a" + 1` + (ResolvedPythonType::Atom(_), ResolvedPythonType::Atom(_)) => { + return ResolvedPythonType::TypeError; + } + _ => {} + } + } + Operator::Sub => { + match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `1 - 1` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + return ResolvedPythonType::Atom(PythonType::Number( + left.coerce(right), + )); + } + // Ex) `{1, 2} - {2}` + ( + ResolvedPythonType::Atom(PythonType::Set), + ResolvedPythonType::Atom(PythonType::Set), + ) => return ResolvedPythonType::Atom(PythonType::Set), + // Ex) `"a" - "b"` + (ResolvedPythonType::Atom(_), ResolvedPythonType::Atom(_)) => { + return ResolvedPythonType::TypeError; + } + _ => {} + } + } + // Ex) "a" % "b" + Operator::Mod => match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `"Hello" % "world"` + (ResolvedPythonType::Atom(PythonType::String), _) => { + return ResolvedPythonType::Atom(PythonType::String) + } + // Ex) `b"Hello" % b"world"` + (ResolvedPythonType::Atom(PythonType::Bytes), _) => { + return ResolvedPythonType::Atom(PythonType::Bytes) + } + // Ex) `1 % 2` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + return ResolvedPythonType::Atom(PythonType::Number( + left.coerce(right), + )); + } + _ => {} + }, + // Standard arithmetic operators, which coerce to the "highest" number type. + Operator::Mult | Operator::FloorDiv | Operator::Pow => match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `1 - 2` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + return ResolvedPythonType::Atom(PythonType::Number( + left.coerce(right), + )); + } + (ResolvedPythonType::Atom(_), ResolvedPythonType::Atom(_)) => { + return ResolvedPythonType::TypeError; + } + _ => {} + }, + // Division, which returns at least `float`. + Operator::Div => match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `1 / 2` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + let resolved = left.coerce(right); + return ResolvedPythonType::Atom(PythonType::Number( + if resolved == NumberLike::Integer { + NumberLike::Float + } else { + resolved + }, + )); + } + (ResolvedPythonType::Atom(_), ResolvedPythonType::Atom(_)) => { + return ResolvedPythonType::TypeError; + } + _ => {} + }, + // Bitwise operators, which only work on `int` and `bool`. + Operator::BitAnd + | Operator::BitOr + | Operator::BitXor + | Operator::LShift + | Operator::RShift => { + match ( + ResolvedPythonType::from(left.as_ref()), + ResolvedPythonType::from(right.as_ref()), + ) { + // Ex) `1 & 2` + ( + ResolvedPythonType::Atom(PythonType::Number(left)), + ResolvedPythonType::Atom(PythonType::Number(right)), + ) => { + let resolved = left.coerce(right); + return if resolved == NumberLike::Integer { + ResolvedPythonType::Atom(PythonType::Number( + NumberLike::Integer, + )) + } else { + ResolvedPythonType::TypeError + }; + } + (ResolvedPythonType::Atom(_), ResolvedPythonType::Atom(_)) => { + return ResolvedPythonType::TypeError; + } + _ => {} + } + } + Operator::MatMult => {} + } + ResolvedPythonType::Unknown + } + Expr::Lambda(_) + | Expr::Await(_) + | Expr::Yield(_) + | Expr::YieldFrom(_) + | Expr::Compare(_) + | Expr::Call(_) + | Expr::FormattedValue(_) + | Expr::Attribute(_) + | Expr::Subscript(_) + | Expr::Starred(_) + | Expr::Name(_) + | Expr::Slice(_) + | Expr::IpyEscapeCommand(_) => ResolvedPythonType::Unknown, + } + } +} /// An extremely simple type inference system for individual expressions. /// @@ -9,20 +319,14 @@ use ruff_python_ast::{Constant, Expr}; /// such as strings, integers, floats, and containers. It cannot infer the /// types of variables or expressions that are not statically known from /// individual AST nodes alone. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum PythonType { /// A string literal, such as `"hello"`. String, /// A bytes literal, such as `b"hello"`. Bytes, - /// An integer literal, such as `1` or `0x1`. - Integer, - /// A floating-point literal, such as `1.0` or `1e10`. - Float, - /// A complex literal, such as `1j` or `1+1j`. - Complex, - /// A boolean literal, such as `True` or `False`. - Bool, + /// An integer, float, or complex literal, such as `1` or `1.0`. + Number(NumberLike), /// A `None` literal, such as `None`. None, /// An ellipsis literal, such as `...`. @@ -37,59 +341,149 @@ pub enum PythonType { Tuple, /// A generator expression, such as `(x for x in range(10))`. Generator, - /// An unknown type, such as a variable or function call. - Unknown, } -impl From<&Expr> for PythonType { - fn from(expr: &Expr) -> Self { - match expr { - Expr::NamedExpr(ast::ExprNamedExpr { value, .. }) => (value.as_ref()).into(), - Expr::UnaryOp(ast::ExprUnaryOp { operand, .. }) => (operand.as_ref()).into(), - Expr::Dict(_) => PythonType::Dict, - Expr::DictComp(_) => PythonType::Dict, - Expr::Set(_) => PythonType::Set, - Expr::SetComp(_) => PythonType::Set, - Expr::List(_) => PythonType::List, - Expr::ListComp(_) => PythonType::List, - Expr::Tuple(_) => PythonType::Tuple, - Expr::GeneratorExp(_) => PythonType::Generator, - Expr::JoinedStr(_) => PythonType::String, - Expr::BinOp(ast::ExprBinOp { left, op, .. }) => { - // Ex) "a" % "b" - if op.is_mod() { - if matches!( - left.as_ref(), - Expr::Constant(ast::ExprConstant { - value: Constant::Str(..), - .. - }) - ) { - return PythonType::String; - } - if matches!( - left.as_ref(), - Expr::Constant(ast::ExprConstant { - value: Constant::Bytes(..), - .. - }) - ) { - return PythonType::Bytes; - } - } - PythonType::Unknown - } - Expr::Constant(ast::ExprConstant { value, .. }) => match value { - Constant::Str(_) => PythonType::String, - Constant::Int(_) => PythonType::Integer, - Constant::Float(_) => PythonType::Float, - Constant::Bool(_) => PythonType::Bool, - Constant::Complex { .. } => PythonType::Complex, - Constant::None => PythonType::None, - Constant::Ellipsis => PythonType::Ellipsis, - Constant::Bytes(_) => PythonType::Bytes, - }, - _ => PythonType::Unknown, +/// A numeric type, or a type that can be trivially coerced to a numeric type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum NumberLike { + /// An integer literal, such as `1` or `0x1`. + Integer, + /// A floating-point literal, such as `1.0` or `1e10`. + Float, + /// A complex literal, such as `1j` or `1+1j`. + Complex, + /// A boolean literal, such as `True` or `False`. + Bool, +} + +impl NumberLike { + /// Coerces two number-like types to the "highest" number-like type. + #[must_use] + pub fn coerce(self, other: NumberLike) -> NumberLike { + match (self, other) { + (NumberLike::Complex, _) | (_, NumberLike::Complex) => NumberLike::Complex, + (NumberLike::Float, _) | (_, NumberLike::Float) => NumberLike::Float, + _ => NumberLike::Integer, } } } + +#[cfg(test)] +mod tests { + use rustc_hash::FxHashSet; + + use ruff_python_ast::Expr; + use ruff_python_parser::parse_expression; + + use crate::analyze::type_inference::{NumberLike, PythonType, ResolvedPythonType}; + + fn parse(expression: &str) -> Expr { + parse_expression(expression, "").unwrap() + } + + #[test] + fn type_inference() { + // Atoms. + assert_eq!( + ResolvedPythonType::from(&parse("1")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("'Hello, world'")), + ResolvedPythonType::Atom(PythonType::String) + ); + assert_eq!( + ResolvedPythonType::from(&parse("b'Hello, world'")), + ResolvedPythonType::Atom(PythonType::Bytes) + ); + assert_eq!( + ResolvedPythonType::from(&parse("'Hello' % 'world'")), + ResolvedPythonType::Atom(PythonType::String) + ); + + // Boolean operators. + assert_eq!( + ResolvedPythonType::from(&parse("1 and 2")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1 and True")), + ResolvedPythonType::Union(FxHashSet::from_iter([ + PythonType::Number(NumberLike::Integer), + PythonType::Number(NumberLike::Bool) + ])) + ); + + // Binary operators. + assert_eq!( + ResolvedPythonType::from(&parse("1.0 * 2")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("2 * 1.0")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1.0 * 2j")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Complex)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1 / True")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1 / 2")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("{1, 2} - {2}")), + ResolvedPythonType::Atom(PythonType::Set) + ); + + // Unary operators. + assert_eq!( + ResolvedPythonType::from(&parse("-1")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("-1.0")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Float)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("-1j")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Complex)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("-True")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("not 'Hello'")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Bool)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("not x.y.z")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Bool)) + ); + + // Conditional expressions. + assert_eq!( + ResolvedPythonType::from(&parse("1 if True else 2")), + ResolvedPythonType::Atom(PythonType::Number(NumberLike::Integer)) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1 if True else 2.0")), + ResolvedPythonType::Union(FxHashSet::from_iter([ + PythonType::Number(NumberLike::Integer), + PythonType::Number(NumberLike::Float) + ])) + ); + assert_eq!( + ResolvedPythonType::from(&parse("1 if True else False")), + ResolvedPythonType::Union(FxHashSet::from_iter([ + PythonType::Number(NumberLike::Integer), + PythonType::Number(NumberLike::Bool) + ])) + ); + } +} diff --git a/crates/ruff_python_semantic/src/analyze/typing.rs b/crates/ruff_python_semantic/src/analyze/typing.rs index ea642026d875f..b2c4b52f3523a 100644 --- a/crates/ruff_python_semantic/src/analyze/typing.rs +++ b/crates/ruff_python_semantic/src/analyze/typing.rs @@ -116,7 +116,7 @@ pub fn to_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> Option bool { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { let [module, name] = call_path.as_slice() else { return false; }; @@ -186,45 +186,57 @@ pub fn to_pep604_operator( /// Return `true` if `Expr` represents a reference to a type annotation that resolves to an /// immutable type. -pub fn is_immutable_annotation(expr: &Expr, semantic: &SemanticModel) -> bool { +pub fn is_immutable_annotation( + expr: &Expr, + semantic: &SemanticModel, + extend_immutable_calls: &[CallPath], +) -> bool { match expr { Expr::Name(_) | Expr::Attribute(_) => { - semantic.resolve_call_path(expr).map_or(false, |call_path| { + semantic.resolve_call_path(expr).is_some_and(|call_path| { is_immutable_non_generic_type(call_path.as_slice()) || is_immutable_generic_type(call_path.as_slice()) + || extend_immutable_calls + .iter() + .any(|target| call_path == *target) }) } - Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => semantic - .resolve_call_path(value) - .map_or(false, |call_path| { + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { + semantic.resolve_call_path(value).is_some_and(|call_path| { if is_immutable_generic_type(call_path.as_slice()) { true } else if matches!(call_path.as_slice(), ["typing", "Union"]) { if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() { - elts.iter() - .all(|elt| is_immutable_annotation(elt, semantic)) + elts.iter().all(|elt| { + is_immutable_annotation(elt, semantic, extend_immutable_calls) + }) } else { false } } else if matches!(call_path.as_slice(), ["typing", "Optional"]) { - is_immutable_annotation(slice, semantic) - } else if matches!(call_path.as_slice(), ["typing", "Annotated"]) { + is_immutable_annotation(slice, semantic, extend_immutable_calls) + } else if is_pep_593_generic_type(call_path.as_slice()) { if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() { - elts.first() - .map_or(false, |elt| is_immutable_annotation(elt, semantic)) + elts.first().is_some_and(|elt| { + is_immutable_annotation(elt, semantic, extend_immutable_calls) + }) } else { false } } else { false } - }), + }) + } Expr::BinOp(ast::ExprBinOp { left, op: Operator::BitOr, right, - range: _range, - }) => is_immutable_annotation(left, semantic) && is_immutable_annotation(right, semantic), + range: _, + }) => { + is_immutable_annotation(left, semantic, extend_immutable_calls) + && is_immutable_annotation(right, semantic, extend_immutable_calls) + } Expr::Constant(ast::ExprConstant { value: Constant::None, .. @@ -239,7 +251,7 @@ pub fn is_immutable_func( semantic: &SemanticModel, extend_immutable_calls: &[CallPath], ) -> bool { - semantic.resolve_call_path(func).map_or(false, |call_path| { + semantic.resolve_call_path(func).is_some_and(|call_path| { is_immutable_return_type(call_path.as_slice()) || extend_immutable_calls .iter() @@ -253,7 +265,7 @@ pub fn is_mutable_func(func: &Expr, semantic: &SemanticModel) -> bool { .resolve_call_path(func) .as_ref() .map(CallPath::as_slice) - .map_or(false, is_mutable_return_type) + .is_some_and(is_mutable_return_type) } /// Return `true` if `expr` is an expression that resolves to a mutable value. @@ -291,9 +303,10 @@ pub fn is_type_checking_block(stmt: &ast::StmtIf, semantic: &SemanticModel) -> b } // Ex) `if typing.TYPE_CHECKING:` - if semantic.resolve_call_path(test).map_or(false, |call_path| { - matches!(call_path.as_slice(), ["typing", "TYPE_CHECKING"]) - }) { + if semantic + .resolve_call_path(test) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "TYPE_CHECKING"])) + { return true; } diff --git a/crates/ruff_python_semantic/src/analyze/visibility.rs b/crates/ruff_python_semantic/src/analyze/visibility.rs index 4817d81b6695e..28dae7c0c61aa 100644 --- a/crates/ruff_python_semantic/src/analyze/visibility.rs +++ b/crates/ruff_python_semantic/src/analyze/visibility.rs @@ -1,6 +1,6 @@ use std::path::Path; -use ruff_python_ast::{self as ast, Decorator, Stmt}; +use ruff_python_ast::{self as ast, Decorator}; use ruff_python_ast::call_path::{collect_call_path, CallPath}; use ruff_python_ast::helpers::map_callable; @@ -18,9 +18,7 @@ pub fn is_staticmethod(decorator_list: &[Decorator], semantic: &SemanticModel) - decorator_list.iter().any(|decorator| { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "staticmethod"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "staticmethod"])) }) } @@ -29,9 +27,7 @@ pub fn is_classmethod(decorator_list: &[Decorator], semantic: &SemanticModel) -> decorator_list.iter().any(|decorator| { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { - matches!(call_path.as_slice(), ["", "classmethod"]) - }) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["", "classmethod"])) }) } @@ -54,7 +50,7 @@ pub fn is_abstract(decorator_list: &[Decorator], semantic: &SemanticModel) -> bo decorator_list.iter().any(|decorator| { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), [ @@ -80,7 +76,7 @@ pub fn is_property( decorator_list.iter().any(|decorator| { semantic .resolve_call_path(map_callable(&decorator.expression)) - .map_or(false, |call_path| { + .is_some_and(|call_path| { matches!( call_path.as_slice(), ["", "property"] | ["functools", "cached_property"] @@ -180,67 +176,42 @@ impl ModuleSource<'_> { } } -pub(crate) fn function_visibility(stmt: &Stmt) -> Visibility { - match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) => { - if name.starts_with('_') { - Visibility::Private - } else { - Visibility::Public - } - } - _ => panic!("Found non-FunctionDef in function_visibility"), +pub(crate) fn function_visibility(function: &ast::StmtFunctionDef) -> Visibility { + if function.name.starts_with('_') { + Visibility::Private + } else { + Visibility::Public } } -pub(crate) fn method_visibility(stmt: &Stmt) -> Visibility { - match stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { - name, - decorator_list, - .. +pub(crate) fn method_visibility(function: &ast::StmtFunctionDef) -> Visibility { + // Is this a setter or deleter? + if function.decorator_list.iter().any(|decorator| { + collect_call_path(&decorator.expression).is_some_and(|call_path| { + call_path.as_slice() == [function.name.as_str(), "setter"] + || call_path.as_slice() == [function.name.as_str(), "deleter"] }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { - name, - decorator_list, - .. - }) => { - // Is this a setter or deleter? - if decorator_list.iter().any(|decorator| { - collect_call_path(&decorator.expression).map_or(false, |call_path| { - call_path.as_slice() == [name, "setter"] - || call_path.as_slice() == [name, "deleter"] - }) - }) { - return Visibility::Private; - } - - // Is the method non-private? - if !name.starts_with('_') { - return Visibility::Public; - } + }) { + return Visibility::Private; + } - // Is this a magic method? - if name.starts_with("__") && name.ends_with("__") { - return Visibility::Public; - } + // Is the method non-private? + if !function.name.starts_with('_') { + return Visibility::Public; + } - Visibility::Private - } - _ => panic!("Found non-FunctionDef in method_visibility"), + // Is this a magic method? + if function.name.starts_with("__") && function.name.ends_with("__") { + return Visibility::Public; } + + Visibility::Private } -pub(crate) fn class_visibility(stmt: &Stmt) -> Visibility { - match stmt { - Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { - if name.starts_with('_') { - Visibility::Private - } else { - Visibility::Public - } - } - _ => panic!("Found non-ClassDef in function_visibility"), +pub(crate) fn class_visibility(class: &ast::StmtClassDef) -> Visibility { + if class.name.starts_with('_') { + Visibility::Private + } else { + Visibility::Public } } diff --git a/crates/ruff_python_semantic/src/binding.rs b/crates/ruff_python_semantic/src/binding.rs index 7dd9056dd6c45..ea4113e6c8afe 100644 --- a/crates/ruff_python_semantic/src/binding.rs +++ b/crates/ruff_python_semantic/src/binding.rs @@ -1,15 +1,17 @@ +use std::borrow::Cow; use std::ops::{Deref, DerefMut}; use bitflags::bitflags; -use ruff_python_ast::Ranged; -use ruff_text_size::TextRange; use ruff_index::{newtype_index, IndexSlice, IndexVec}; +use ruff_python_ast::call_path::format_call_path; +use ruff_python_ast::Ranged; use ruff_source_file::Locator; +use ruff_text_size::TextRange; use crate::context::ExecutionContext; use crate::model::SemanticModel; -use crate::node::NodeId; +use crate::nodes::NodeId; use crate::reference::ResolvedReferenceId; use crate::ScopeId; @@ -117,38 +119,38 @@ impl<'a> Binding<'a> { // import foo.baz // ``` BindingKind::Import(Import { - qualified_name: redefinition, + call_path: redefinition, }) => { if let BindingKind::SubmoduleImport(SubmoduleImport { - qualified_name: definition, + call_path: definition, }) = &existing.kind { return redefinition == definition; } } BindingKind::FromImport(FromImport { - qualified_name: redefinition, + call_path: redefinition, }) => { if let BindingKind::SubmoduleImport(SubmoduleImport { - qualified_name: definition, + call_path: definition, }) = &existing.kind { return redefinition == definition; } } BindingKind::SubmoduleImport(SubmoduleImport { - qualified_name: redefinition, + call_path: redefinition, }) => match &existing.kind { BindingKind::Import(Import { - qualified_name: definition, + call_path: definition, }) | BindingKind::SubmoduleImport(SubmoduleImport { - qualified_name: definition, + call_path: definition, }) => { return redefinition == definition; } BindingKind::FromImport(FromImport { - qualified_name: definition, + call_path: definition, }) => { return redefinition == definition; } @@ -175,35 +177,6 @@ impl<'a> Binding<'a> { ) } - /// Returns the fully-qualified symbol name, if this symbol was imported from another module. - pub fn qualified_name(&self) -> Option<&str> { - match &self.kind { - BindingKind::Import(Import { qualified_name }) => Some(qualified_name), - BindingKind::FromImport(FromImport { qualified_name }) => Some(qualified_name), - BindingKind::SubmoduleImport(SubmoduleImport { qualified_name }) => { - Some(qualified_name) - } - _ => None, - } - } - - /// Returns the fully-qualified name of the module from which this symbol was imported, if this - /// symbol was imported from another module. - pub fn module_name(&self) -> Option<&str> { - match &self.kind { - BindingKind::Import(Import { qualified_name }) - | BindingKind::SubmoduleImport(SubmoduleImport { qualified_name }) => { - Some(qualified_name.split('.').next().unwrap_or(qualified_name)) - } - BindingKind::FromImport(FromImport { qualified_name }) => Some( - qualified_name - .rsplit_once('.') - .map_or(qualified_name, |(module, _)| module), - ), - _ => None, - } - } - /// Returns the name of the binding (e.g., `x` in `x = 1`). pub fn name<'b>(&self, locator: &'b Locator) -> &'b str { locator.slice(self.range) @@ -212,7 +185,7 @@ impl<'a> Binding<'a> { /// Returns the range of the binding's parent. pub fn parent_range(&self, semantic: &SemanticModel) -> Option { self.source - .map(|node_id| semantic.stmts[node_id]) + .map(|id| semantic.statement(id)) .and_then(|parent| { if parent.is_import_from_stmt() { Some(parent.range()) @@ -221,6 +194,15 @@ impl<'a> Binding<'a> { } }) } + + pub fn as_any_import(&'a self) -> Option> { + match &self.kind { + BindingKind::Import(import) => Some(AnyImport::Import(import)), + BindingKind::SubmoduleImport(import) => Some(AnyImport::SubmoduleImport(import)), + BindingKind::FromImport(import) => Some(AnyImport::FromImport(import)), + _ => None, + } + } } bitflags! { @@ -301,6 +283,12 @@ bitflags! { } } +impl Ranged for Binding<'_> { + fn range(&self) -> TextRange { + self.range + } +} + /// ID uniquely identifying a [Binding] in a program. /// /// Using a `u32` to identify [Binding]s should is sufficient because Ruff only supports documents with a @@ -356,18 +344,18 @@ pub struct Import<'a> { /// The full name of the module being imported. /// Ex) Given `import foo`, `qualified_name` would be "foo". /// Ex) Given `import foo as bar`, `qualified_name` would be "foo". - pub qualified_name: &'a str, + pub call_path: Box<[&'a str]>, } /// A binding for a member imported from a module, keyed on the name to which the member is bound. /// Ex) `from foo import bar` would be keyed on "bar". /// Ex) `from foo import bar as baz` would be keyed on "baz". #[derive(Debug, Clone)] -pub struct FromImport { +pub struct FromImport<'a> { /// The full name of the member being imported. /// Ex) Given `from foo import bar`, `qualified_name` would be "foo.bar". /// Ex) Given `from foo import bar as baz`, `qualified_name` would be "foo.bar". - pub qualified_name: String, + pub call_path: Box<[&'a str]>, } /// A binding for a submodule imported from a module, keyed on the name of the parent module. @@ -376,7 +364,7 @@ pub struct FromImport { pub struct SubmoduleImport<'a> { /// The full name of the submodule being imported. /// Ex) Given `import foo.bar`, `qualified_name` would be "foo.bar". - pub qualified_name: &'a str, + pub call_path: Box<[&'a str]>, } #[derive(Debug, Clone, is_macro::Is)] @@ -485,7 +473,7 @@ pub enum BindingKind<'a> { /// ```python /// from foo import bar /// ``` - FromImport(FromImport), + FromImport(FromImport<'a>), /// A binding for a submodule imported from a module, like `bar` in: /// ```python @@ -532,3 +520,106 @@ bitflags! { const IMPORT_ERROR = 0b0000_0100; } } + +/// A trait for imported symbols. +pub trait Imported<'a> { + /// Returns the call path to the imported symbol. + fn call_path(&self) -> &[&str]; + + /// Returns the module name of the imported symbol. + fn module_name(&self) -> &[&str]; + + /// Returns the member name of the imported symbol. For a straight import, this is equivalent + /// to the qualified name; for a `from` import, this is the name of the imported symbol. + fn member_name(&self) -> Cow<'a, str>; + + /// Returns the fully-qualified name of the imported symbol. + fn qualified_name(&self) -> String { + format_call_path(self.call_path()) + } +} + +impl<'a> Imported<'a> for Import<'a> { + /// For example, given `import foo`, returns `["foo"]`. + fn call_path(&self) -> &[&str] { + self.call_path.as_ref() + } + + /// For example, given `import foo`, returns `["foo"]`. + fn module_name(&self) -> &[&str] { + &self.call_path[..1] + } + + /// For example, given `import foo`, returns `"foo"`. + fn member_name(&self) -> Cow<'a, str> { + Cow::Owned(self.qualified_name()) + } +} + +impl<'a> Imported<'a> for SubmoduleImport<'a> { + /// For example, given `import foo.bar`, returns `["foo", "bar"]`. + fn call_path(&self) -> &[&str] { + self.call_path.as_ref() + } + + /// For example, given `import foo.bar`, returns `["foo"]`. + fn module_name(&self) -> &[&str] { + &self.call_path[..1] + } + + /// For example, given `import foo.bar`, returns `"foo.bar"`. + fn member_name(&self) -> Cow<'a, str> { + Cow::Owned(self.qualified_name()) + } +} + +impl<'a> Imported<'a> for FromImport<'a> { + /// For example, given `from foo import bar`, returns `["foo", "bar"]`. + fn call_path(&self) -> &[&str] { + self.call_path.as_ref() + } + + /// For example, given `from foo import bar`, returns `["foo"]`. + fn module_name(&self) -> &[&str] { + &self.call_path[..self.call_path.len() - 1] + } + + /// For example, given `from foo import bar`, returns `"bar"`. + fn member_name(&self) -> Cow<'a, str> { + Cow::Borrowed(self.call_path[self.call_path.len() - 1]) + } +} + +/// A wrapper around an import [`BindingKind`] that can be any of the three types of imports. +#[derive(Debug, Clone, is_macro::Is)] +pub enum AnyImport<'a> { + Import(&'a Import<'a>), + SubmoduleImport(&'a SubmoduleImport<'a>), + FromImport(&'a FromImport<'a>), +} + +impl<'a> Imported<'a> for AnyImport<'a> { + fn call_path(&self) -> &[&str] { + match self { + Self::Import(import) => import.call_path(), + Self::SubmoduleImport(import) => import.call_path(), + Self::FromImport(import) => import.call_path(), + } + } + + fn module_name(&self) -> &[&str] { + match self { + Self::Import(import) => import.module_name(), + Self::SubmoduleImport(import) => import.module_name(), + Self::FromImport(import) => import.module_name(), + } + } + + fn member_name(&self) -> Cow<'a, str> { + match self { + Self::Import(import) => import.member_name(), + Self::SubmoduleImport(import) => import.member_name(), + Self::FromImport(import) => import.member_name(), + } + } +} diff --git a/crates/ruff_python_semantic/src/branches.rs b/crates/ruff_python_semantic/src/branches.rs new file mode 100644 index 0000000000000..477f5522a65e7 --- /dev/null +++ b/crates/ruff_python_semantic/src/branches.rs @@ -0,0 +1,52 @@ +use std::ops::Index; + +use ruff_index::{newtype_index, IndexVec}; + +/// ID uniquely identifying a branch in a program. +/// +/// For example, given: +/// ```python +/// if x > 0: +/// pass +/// elif x > 1: +/// pass +/// else: +/// pass +/// ``` +/// +/// Each of the three arms of the `if`-`elif`-`else` would be considered a branch, and would be +/// assigned their own unique [`BranchId`]. +#[newtype_index] +#[derive(Ord, PartialOrd)] +pub struct BranchId; + +/// The branches of a program indexed by [`BranchId`] +#[derive(Debug, Default)] +pub(crate) struct Branches(IndexVec>); + +impl Branches { + /// Inserts a new branch into the vector and returns its unique [`BranchID`]. + pub(crate) fn insert(&mut self, parent: Option) -> BranchId { + self.0.push(parent) + } + + /// Return the [`BranchId`] of the parent branch. + #[inline] + pub(crate) fn parent_id(&self, node_id: BranchId) -> Option { + self.0[node_id] + } + + /// Returns an iterator over all [`BranchId`] ancestors, starting from the given [`BranchId`]. + pub(crate) fn ancestor_ids(&self, node_id: BranchId) -> impl Iterator + '_ { + std::iter::successors(Some(node_id), |&node_id| self.0[node_id]) + } +} + +impl Index for Branches { + type Output = Option; + + #[inline] + fn index(&self, index: BranchId) -> &Self::Output { + &self.0[index] + } +} diff --git a/crates/ruff_python_semantic/src/definition.rs b/crates/ruff_python_semantic/src/definition.rs index cfb069dde07eb..9c0a20297130b 100644 --- a/crates/ruff_python_semantic/src/definition.rs +++ b/crates/ruff_python_semantic/src/definition.rs @@ -5,7 +5,8 @@ use std::fmt::Debug; use std::ops::Deref; use ruff_index::{newtype_index, IndexSlice, IndexVec}; -use ruff_python_ast::{self as ast, Stmt}; +use ruff_python_ast::{self as ast, Ranged, Stmt}; +use ruff_text_size::TextRange; use crate::analyze::visibility::{ class_visibility, function_visibility, method_visibility, ModuleSource, Visibility, @@ -23,7 +24,7 @@ impl DefinitionId { } } -#[derive(Debug)] +#[derive(Debug, is_macro::Is)] pub enum ModuleKind { /// A Python file that represents a module within a package. Module, @@ -57,36 +58,60 @@ impl<'a> Module<'a> { } } -#[derive(Debug, Copy, Clone)] -pub enum MemberKind { +#[derive(Debug, Copy, Clone, is_macro::Is)] +pub enum MemberKind<'a> { /// A class definition within a program. - Class, + Class(&'a ast::StmtClassDef), /// A nested class definition within a program. - NestedClass, + NestedClass(&'a ast::StmtClassDef), /// A function definition within a program. - Function, + Function(&'a ast::StmtFunctionDef), /// A nested function definition within a program. - NestedFunction, + NestedFunction(&'a ast::StmtFunctionDef), /// A method definition within a program. - Method, + Method(&'a ast::StmtFunctionDef), } /// A member of a Python module. #[derive(Debug)] pub struct Member<'a> { - pub kind: MemberKind, + pub kind: MemberKind<'a>, pub parent: DefinitionId, - pub stmt: &'a Stmt, } impl<'a> Member<'a> { /// Return the name of the member. - pub fn name(&self) -> Option<&'a str> { - match &self.stmt { - Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) - | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { name, .. }) - | Stmt::ClassDef(ast::StmtClassDef { name, .. }) => Some(name), - _ => None, + pub fn name(&self) -> &str { + match self.kind { + MemberKind::Class(class) => &class.name, + MemberKind::NestedClass(class) => &class.name, + MemberKind::Function(function) => &function.name, + MemberKind::NestedFunction(function) => &function.name, + MemberKind::Method(method) => &method.name, + } + } + + /// Return the body of the member. + pub fn body(&self) -> &[Stmt] { + match self.kind { + MemberKind::Class(class) => &class.body, + MemberKind::NestedClass(class) => &class.body, + MemberKind::Function(function) => &function.body, + MemberKind::NestedFunction(function) => &function.body, + MemberKind::Method(method) => &method.body, + } + } +} + +impl Ranged for Member<'_> { + /// Return the range of the member. + fn range(&self) -> TextRange { + match self.kind { + MemberKind::Class(class) => class.range(), + MemberKind::NestedClass(class) => class.range(), + MemberKind::Function(function) => function.range(), + MemberKind::NestedFunction(function) => function.range(), + MemberKind::Method(method) => method.range(), } } } @@ -104,16 +129,42 @@ impl Definition<'_> { matches!( self, Definition::Member(Member { - kind: MemberKind::Method, + kind: MemberKind::Method(_), .. }) ) } + /// Return the name of the definition. pub fn name(&self) -> Option<&str> { match self { Definition::Module(module) => module.name(), - Definition::Member(member) => member.name(), + Definition::Member(member) => Some(member.name()), + } + } + + /// Return the [`ast::StmtFunctionDef`] of the definition, if it's a function definition. + pub fn as_function_def(&self) -> Option<&ast::StmtFunctionDef> { + match self { + Definition::Member(Member { + kind: + MemberKind::Function(function) + | MemberKind::NestedFunction(function) + | MemberKind::Method(function), + .. + }) => Some(function), + _ => None, + } + } + + /// Return the [`ast::StmtClassDef`] of the definition, if it's a class definition. + pub fn as_class_def(&self) -> Option<&ast::StmtClassDef> { + match self { + Definition::Member(Member { + kind: MemberKind::Class(class) | MemberKind::NestedClass(class), + .. + }) => Some(class), + _ => None, } } } @@ -147,55 +198,43 @@ impl<'a> Definitions<'a> { match &definition { Definition::Module(module) => module.source.to_visibility(), Definition::Member(member) => match member.kind { - MemberKind::Class => { + MemberKind::Class(class) => { let parent = &definitions[member.parent]; if parent.visibility.is_private() - || exports.map_or(false, |exports| { - member.name().map_or(false, |name| !exports.contains(&name)) - }) + || exports.is_some_and(|exports| !exports.contains(&member.name())) { Visibility::Private } else { - class_visibility(member.stmt) + class_visibility(class) } } - MemberKind::NestedClass => { + MemberKind::NestedClass(class) => { let parent = &definitions[member.parent]; if parent.visibility.is_private() - || matches!( - parent.definition, - Definition::Member(Member { - kind: MemberKind::Function - | MemberKind::NestedFunction - | MemberKind::Method, - .. - }) - ) + || parent.definition.as_function_def().is_some() { Visibility::Private } else { - class_visibility(member.stmt) + class_visibility(class) } } - MemberKind::Function => { + MemberKind::Function(function) => { let parent = &definitions[member.parent]; if parent.visibility.is_private() - || exports.map_or(false, |exports| { - member.name().map_or(false, |name| !exports.contains(&name)) - }) + || exports.is_some_and(|exports| !exports.contains(&member.name())) { Visibility::Private } else { - function_visibility(member.stmt) + function_visibility(function) } } - MemberKind::NestedFunction => Visibility::Private, - MemberKind::Method => { + MemberKind::NestedFunction(_) => Visibility::Private, + MemberKind::Method(function) => { let parent = &definitions[member.parent]; if parent.visibility.is_private() { Visibility::Private } else { - method_visibility(member.stmt) + method_visibility(function) } } }, diff --git a/crates/ruff_python_semantic/src/globals.rs b/crates/ruff_python_semantic/src/globals.rs index a17b79b6f8fde..ffaf1b16f9dcc 100644 --- a/crates/ruff_python_semantic/src/globals.rs +++ b/crates/ruff_python_semantic/src/globals.rs @@ -80,7 +80,7 @@ impl<'a> StatementVisitor<'a> for GlobalsVisitor<'a> { self.0.insert(name.as_str(), *range); } } - Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) | Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { // Don't recurse. } _ => walk_stmt(self, stmt), diff --git a/crates/ruff_python_semantic/src/lib.rs b/crates/ruff_python_semantic/src/lib.rs index 3b7ce9a7a549e..ce45050239e47 100644 --- a/crates/ruff_python_semantic/src/lib.rs +++ b/crates/ruff_python_semantic/src/lib.rs @@ -1,20 +1,22 @@ pub mod analyze; mod binding; +mod branches; mod context; mod definition; mod globals; mod model; -mod node; +mod nodes; mod reference; mod scope; mod star_import; pub use binding::*; +pub use branches::*; pub use context::*; pub use definition::*; pub use globals::*; pub use model::*; -pub use node::*; +pub use nodes::*; pub use reference::*; pub use scope::*; pub use star_import::*; diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index fc66f668de8cf..ed01d5382dcc3 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -1,43 +1,48 @@ use std::path::Path; use bitflags::bitflags; -use ruff_python_ast::{self as ast, Expr, Ranged, Stmt}; -use ruff_text_size::{TextRange, TextSize}; use rustc_hash::FxHashMap; use smallvec::smallvec; use ruff_python_ast::call_path::{collect_call_path, from_unqualified_name, CallPath}; use ruff_python_ast::helpers::from_relative_import; +use ruff_python_ast::{self as ast, Expr, Operator, Ranged, Stmt}; use ruff_python_stdlib::path::is_python_stub_file; use ruff_python_stdlib::typing::is_typing_extension; +use ruff_text_size::{TextRange, TextSize}; use crate::binding::{ Binding, BindingFlags, BindingId, BindingKind, Bindings, Exceptions, FromImport, Import, SubmoduleImport, }; +use crate::branches::{BranchId, Branches}; use crate::context::ExecutionContext; use crate::definition::{Definition, DefinitionId, Definitions, Member, Module}; use crate::globals::{Globals, GlobalsArena}; -use crate::node::{NodeId, Nodes}; +use crate::nodes::{NodeId, NodeRef, Nodes}; use crate::reference::{ - ResolvedReference, ResolvedReferenceId, ResolvedReferences, UnresolvedReferences, + ResolvedReference, ResolvedReferenceId, ResolvedReferences, UnresolvedReference, + UnresolvedReferenceFlags, UnresolvedReferences, }; use crate::scope::{Scope, ScopeId, ScopeKind, Scopes}; -use crate::{UnresolvedReference, UnresolvedReferenceFlags}; +use crate::Imported; /// A semantic model for a Python module, to enable querying the module's semantic information. pub struct SemanticModel<'a> { typing_modules: &'a [String], module_path: Option<&'a [String]>, - /// Stack of all visited statements. - pub stmts: Nodes<'a>, + /// Stack of all AST nodes in the program. + nodes: Nodes<'a>, + + /// The ID of the current AST node. + node_id: Option, - /// The identifier of the current statement. - stmt_id: Option, + /// Stack of all branches in the program. + branches: Branches, - /// Stack of current expressions. - exprs: Vec<&'a Expr>, + /// The ID of the current branch. + branch_id: Option, /// Stack of all scopes, along with the identifier of the current scope. pub scopes: Scopes<'a>, @@ -129,9 +134,10 @@ impl<'a> SemanticModel<'a> { Self { typing_modules, module_path: module.path(), - stmts: Nodes::default(), - stmt_id: None, - exprs: Vec::default(), + nodes: Nodes::default(), + node_id: None, + branches: Branches::default(), + branch_id: None, scopes: Scopes::default(), scope_id: ScopeId::global(), definitions: Definitions::for_module(module), @@ -163,9 +169,8 @@ impl<'a> SemanticModel<'a> { /// Return `true` if the `Expr` is a reference to `typing.${target}`. pub fn match_typing_expr(&self, expr: &Expr, target: &str) -> bool { - self.resolve_call_path(expr).map_or(false, |call_path| { - self.match_typing_call_path(&call_path, target) - }) + self.resolve_call_path(expr) + .is_some_and(|call_path| self.match_typing_call_path(&call_path, target)) } /// Return `true` if the call path is a reference to `typing.${target}`. @@ -222,19 +227,12 @@ impl<'a> SemanticModel<'a> { flags, references: Vec::new(), scope: self.scope_id, - source: self.stmt_id, + source: self.node_id, context: self.execution_context(), exceptions: self.exceptions(), }) } - /// Return the current [`Binding`] for a given `name`. - pub fn find_binding(&self, member: &str) -> Option<&Binding> { - self.scopes() - .find_map(|scope| scope.get(member)) - .map(|binding_id| &self.bindings[binding_id]) - } - /// Return the [`BindingId`] that the given [`BindingId`] shadows, if any. /// /// Note that this will only return bindings that are shadowed by a binding in a parent scope. @@ -244,14 +242,16 @@ impl<'a> SemanticModel<'a> { /// Return `true` if `member` is bound as a builtin. pub fn is_builtin(&self, member: &str) -> bool { - self.find_binding(member) - .map_or(false, |binding| binding.kind.is_builtin()) + self.lookup_symbol(member) + .map(|binding_id| &self.bindings[binding_id]) + .is_some_and(|binding| binding.kind.is_builtin()) } /// Return `true` if `member` is an "available" symbol, i.e., a symbol that has not been bound /// in the current scope, or in any containing scope. pub fn is_available(&self, member: &str) -> bool { - self.find_binding(member) + self.lookup_symbol(member) + .map(|binding_id| &self.bindings[binding_id]) .map_or(true, |binding| binding.kind.is_builtin()) } @@ -473,7 +473,7 @@ impl<'a> SemanticModel<'a> { } } - seen_function |= scope.kind.is_any_function(); + seen_function |= scope.kind.is_function(); import_starred = import_starred || scope.uses_star_imports(); } @@ -535,7 +535,7 @@ impl<'a> SemanticModel<'a> { } } - seen_function |= scope.kind.is_any_function(); + seen_function |= scope.kind.is_function(); } None @@ -584,24 +584,38 @@ impl<'a> SemanticModel<'a> { // import pyarrow.csv // print(pa.csv.read_csv("test.csv")) // ``` - let qualified_name = self.bindings[binding_id].qualified_name()?; - let has_alias = qualified_name - .split('.') - .last() - .map(|segment| segment != symbol) - .unwrap_or_default(); - if !has_alias { + let import = self.bindings[binding_id].as_any_import()?; + if !import.is_import() { + return None; + } + + // Grab, e.g., `pyarrow` from `import pyarrow as pa`. + let call_path = import.call_path(); + let segment = call_path.last()?; + if *segment == symbol { return None; } - let binding_id = self.scopes[scope_id].get(qualified_name)?; - if !self.bindings[binding_id].kind.is_submodule_import() { + // Locate the submodule import (e.g., `pyarrow.csv`) that `pa` aliases. + let binding_id = self.scopes[scope_id].get(segment)?; + let submodule = &self.bindings[binding_id].as_any_import()?; + if !submodule.is_submodule_import() { + return None; + } + + // Ensure that the submodule import and the aliased import are from the same module. + if import.module_name() != submodule.module_name() { return None; } Some(binding_id) } + /// Resolves the [`ast::ExprName`] to the [`BindingId`] of the symbol it refers to, if any. + pub fn resolve_name(&self, name: &ast::ExprName) -> Option { + self.resolved_names.get(&name.into()).copied() + } + /// Resolves the [`Expr`] to a fully-qualified symbol-name, if `value` resolves to an imported /// or builtin symbol. /// @@ -627,52 +641,39 @@ impl<'a> SemanticModel<'a> { // If the name was already resolved, look it up; otherwise, search for the symbol. let head = match_head(value)?; let binding = self - .resolved_names - .get(&head.into()) - .map(|id| self.binding(*id)) - .or_else(|| self.find_binding(&head.id))?; + .resolve_name(head) + .or_else(|| self.lookup_symbol(&head.id)) + .map(|id| self.binding(id))?; match &binding.kind { - BindingKind::Import(Import { - qualified_name: name, - }) => { - let call_path = collect_call_path(value)?; - let (_, tail) = call_path.split_first()?; - - let mut source_path: CallPath = from_unqualified_name(name); - source_path.extend_from_slice(tail); - Some(source_path) + BindingKind::Import(Import { call_path }) => { + let value_path = collect_call_path(value)?; + let (_, tail) = value_path.split_first()?; + let resolved: CallPath = call_path.iter().chain(tail.iter()).copied().collect(); + Some(resolved) } - BindingKind::SubmoduleImport(SubmoduleImport { - qualified_name: name, - }) => { - let call_path = collect_call_path(value)?; - let (_, tail) = call_path.split_first()?; - - let name = name.split('.').next().unwrap_or(name); - let mut source_path: CallPath = from_unqualified_name(name); - source_path.extend_from_slice(tail); - Some(source_path) + BindingKind::SubmoduleImport(SubmoduleImport { call_path }) => { + let value_path = collect_call_path(value)?; + let (_, tail) = value_path.split_first()?; + let resolved: CallPath = call_path + .iter() + .take(1) + .chain(tail.iter()) + .copied() + .collect(); + Some(resolved) } - BindingKind::FromImport(FromImport { - qualified_name: name, - }) => { - let call_path = collect_call_path(value)?; - let (_, tail) = call_path.split_first()?; - - if name.starts_with('.') { - let mut source_path = from_relative_import(self.module_path?, name); - if source_path.is_empty() { - None + BindingKind::FromImport(FromImport { call_path }) => { + let value_path = collect_call_path(value)?; + let (_, tail) = value_path.split_first()?; + + let resolved: CallPath = + if call_path.first().map_or(false, |segment| *segment == ".") { + from_relative_import(self.module_path?, call_path, tail)? } else { - source_path.extend_from_slice(tail); - Some(source_path) - } - } else { - let mut source_path: CallPath = from_unqualified_name(name); - source_path.extend_from_slice(tail); - Some(source_path) - } + call_path.iter().chain(tail.iter()).copied().collect() + }; + Some(resolved) } BindingKind::Builtin => Some(smallvec!["", head.id.as_str()]), _ => None, @@ -696,104 +697,97 @@ impl<'a> SemanticModel<'a> { module: &str, member: &str, ) -> Option { - self.scopes().enumerate().find_map(|(scope_index, scope)| { - scope.bindings().find_map(|(name, binding_id)| { - let binding = &self.bindings[binding_id]; - match &binding.kind { - // Ex) Given `module="sys"` and `object="exit"`: - // `import sys` -> `sys.exit` - // `import sys as sys2` -> `sys2.exit` - BindingKind::Import(Import { qualified_name }) => { - if qualified_name == &module { - if let Some(source) = binding.source { - // Verify that `sys` isn't bound in an inner scope. - if self - .scopes() - .take(scope_index) - .all(|scope| !scope.has(name)) - { - return Some(ImportedName { - name: format!("{name}.{member}"), - range: self.stmts[source].range(), - context: binding.context, - }); - } - } - } - } - // Ex) Given `module="os.path"` and `object="join"`: - // `from os.path import join` -> `join` - // `from os.path import join as join2` -> `join2` - BindingKind::FromImport(FromImport { qualified_name }) => { - if let Some((target_module, target_member)) = qualified_name.split_once('.') - { - if target_module == module && target_member == member { + // TODO(charlie): Pass in a slice. + let module_path: Vec<&str> = module.split('.').collect(); + self.current_scopes() + .enumerate() + .find_map(|(scope_index, scope)| { + scope.bindings().find_map(|(name, binding_id)| { + let binding = &self.bindings[binding_id]; + match &binding.kind { + // Ex) Given `module="sys"` and `object="exit"`: + // `import sys` -> `sys.exit` + // `import sys as sys2` -> `sys2.exit` + BindingKind::Import(Import { call_path }) => { + if call_path.as_ref() == module_path.as_slice() { if let Some(source) = binding.source { - // Verify that `join` isn't bound in an inner scope. + // Verify that `sys` isn't bound in an inner scope. if self - .scopes() + .current_scopes() .take(scope_index) .all(|scope| !scope.has(name)) { return Some(ImportedName { - name: (*name).to_string(), - range: self.stmts[source].range(), + name: format!("{name}.{member}"), + range: self.nodes[source].range(), context: binding.context, }); } } } } - } - // Ex) Given `module="os"` and `object="name"`: - // `import os.path ` -> `os.name` - BindingKind::SubmoduleImport(SubmoduleImport { .. }) => { - if name == module { - if let Some(source) = binding.source { - // Verify that `os` isn't bound in an inner scope. - if self - .scopes() - .take(scope_index) - .all(|scope| !scope.has(name)) + // Ex) Given `module="os.path"` and `object="join"`: + // `from os.path import join` -> `join` + // `from os.path import join as join2` -> `join2` + BindingKind::FromImport(FromImport { call_path }) => { + if let Some((target_member, target_module)) = call_path.split_last() { + if target_module == module_path.as_slice() + && target_member == &member { - return Some(ImportedName { - name: format!("{name}.{member}"), - range: self.stmts[source].range(), - context: binding.context, - }); + if let Some(source) = binding.source { + // Verify that `join` isn't bound in an inner scope. + if self + .current_scopes() + .take(scope_index) + .all(|scope| !scope.has(name)) + { + return Some(ImportedName { + name: (*name).to_string(), + range: self.nodes[source].range(), + context: binding.context, + }); + } + } } } } + // Ex) Given `module="os"` and `object="name"`: + // `import os.path ` -> `os.name` + BindingKind::SubmoduleImport(SubmoduleImport { .. }) => { + if name == module { + if let Some(source) = binding.source { + // Verify that `os` isn't bound in an inner scope. + if self + .current_scopes() + .take(scope_index) + .all(|scope| !scope.has(name)) + { + return Some(ImportedName { + name: format!("{name}.{member}"), + range: self.nodes[source].range(), + context: binding.context, + }); + } + } + } + } + // Non-imports. + _ => {} } - // Non-imports. - _ => {} - } - None + None + }) }) - }) - } - - /// Push a [`Stmt`] onto the stack. - pub fn push_stmt(&mut self, stmt: &'a Stmt) { - self.stmt_id = Some(self.stmts.insert(stmt, self.stmt_id)); } - /// Pop the current [`Stmt`] off the stack. - pub fn pop_stmt(&mut self) { - let node_id = self.stmt_id.expect("Attempted to pop without statement"); - self.stmt_id = self.stmts.parent_id(node_id); + /// Push an AST node [`NodeRef`] onto the stack. + pub fn push_node>>(&mut self, node: T) { + self.node_id = Some(self.nodes.insert(node.into(), self.node_id, self.branch_id)); } - /// Push an [`Expr`] onto the stack. - pub fn push_expr(&mut self, expr: &'a Expr) { - self.exprs.push(expr); - } - - /// Pop the current [`Expr`] off the stack. - pub fn pop_expr(&mut self) { - self.exprs - .pop() - .expect("Attempted to pop without expression"); + /// Pop the current AST node [`NodeRef`] off the stack. + pub fn pop_node(&mut self) { + let node_id = self.node_id.expect("Attempted to pop without node"); + self.node_id = self.nodes.parent_id(node_id); } /// Push a [`Scope`] with the given [`ScopeKind`] onto the stack. @@ -822,60 +816,125 @@ impl<'a> SemanticModel<'a> { self.definition_id = member.parent; } - /// Return the current `Stmt`. - pub fn stmt(&self) -> &'a Stmt { - let node_id = self.stmt_id.expect("No current statement"); - self.stmts[node_id] + /// Push a new branch onto the stack, returning its [`BranchId`]. + pub fn push_branch(&mut self) -> Option { + self.branch_id = Some(self.branches.insert(self.branch_id)); + self.branch_id + } + + /// Pop the current [`BranchId`] off the stack. + pub fn pop_branch(&mut self) { + let node_id = self.branch_id.expect("Attempted to pop without branch"); + self.branch_id = self.branches.parent_id(node_id); + } + + /// Set the current [`BranchId`]. + pub fn set_branch(&mut self, branch_id: Option) { + self.branch_id = branch_id; + } + + /// Returns an [`Iterator`] over the current statement hierarchy, from the current [`Stmt`] + /// through to any parents. + pub fn current_statements(&self) -> impl Iterator + '_ { + let id = self.node_id.expect("No current node"); + self.nodes + .ancestor_ids(id) + .filter_map(move |id| self.nodes[id].as_statement()) + } + + /// Return the current [`Stmt`]. + pub fn current_statement(&self) -> &'a Stmt { + self.current_statements() + .next() + .expect("No current statement") + } + + /// Return the parent [`Stmt`] of the current [`Stmt`], if any. + pub fn current_statement_parent(&self) -> Option<&'a Stmt> { + self.current_statements().nth(1) } - /// Return the parent `Stmt` of the current `Stmt`, if any. - pub fn stmt_parent(&self) -> Option<&'a Stmt> { - let node_id = self.stmt_id.expect("No current statement"); - let parent_id = self.stmts.parent_id(node_id)?; - Some(self.stmts[parent_id]) + /// Returns an [`Iterator`] over the current expression hierarchy, from the current [`Expr`] + /// through to any parents. + pub fn current_expressions(&self) -> impl Iterator + '_ { + let id = self.node_id.expect("No current node"); + self.nodes + .ancestor_ids(id) + .filter_map(move |id| self.nodes[id].as_expression()) } - /// Return the current `Expr`. - pub fn expr(&self) -> Option<&'a Expr> { - self.exprs.iter().last().copied() + /// Return the current [`Expr`]. + pub fn current_expression(&self) -> Option<&'a Expr> { + self.current_expressions().next() } - /// Return the parent `Expr` of the current `Expr`. - pub fn expr_parent(&self) -> Option<&'a Expr> { - self.exprs.iter().rev().nth(1).copied() + /// Return the parent [`Expr`] of the current [`Expr`], if any. + pub fn current_expression_parent(&self) -> Option<&'a Expr> { + self.current_expressions().nth(1) } - /// Return the grandparent `Expr` of the current `Expr`. - pub fn expr_grandparent(&self) -> Option<&'a Expr> { - self.exprs.iter().rev().nth(2).copied() + /// Return the grandparent [`Expr`] of the current [`Expr`], if any. + pub fn current_expression_grandparent(&self) -> Option<&'a Expr> { + self.current_expressions().nth(2) } - /// Return an [`Iterator`] over the current `Expr` parents. - pub fn expr_ancestors(&self) -> impl Iterator { - self.exprs.iter().rev().skip(1) + /// Returns an [`Iterator`] over the current statement hierarchy represented as [`NodeId`], + /// from the current [`NodeId`] through to any parents. + pub fn current_statement_ids(&self) -> impl Iterator + '_ { + self.node_id + .iter() + .flat_map(|id| self.nodes.ancestor_ids(*id)) + .filter(|id| self.nodes[*id].is_statement()) } - /// Returns a reference to the global scope + /// Return the [`NodeId`] of the current [`Stmt`]. + pub fn current_statement_id(&self) -> NodeId { + self.current_statement_ids() + .next() + .expect("No current statement") + } + + /// Return the [`NodeId`] of the current [`Stmt`] parent, if any. + pub fn current_statement_parent_id(&self) -> Option { + self.current_statement_ids().nth(1) + } + + /// Returns a reference to the global [`Scope`]. pub fn global_scope(&self) -> &Scope<'a> { self.scopes.global() } - /// Returns a mutable reference to the global scope + /// Returns a mutable reference to the global [`Scope`]. pub fn global_scope_mut(&mut self) -> &mut Scope<'a> { self.scopes.global_mut() } - /// Returns the current top most scope. - pub fn scope(&self) -> &Scope<'a> { + /// Returns the current top-most [`Scope`]. + pub fn current_scope(&self) -> &Scope<'a> { &self.scopes[self.scope_id] } - /// Returns the parent of the given scope, if any. + /// Returns a mutable reference to the current top-most [`Scope`]. + pub fn current_scope_mut(&mut self) -> &mut Scope<'a> { + &mut self.scopes[self.scope_id] + } + + /// Returns an iterator over all scopes, starting from the current [`Scope`]. + pub fn current_scopes(&self) -> impl Iterator { + self.scopes.ancestors(self.scope_id) + } + + /// Returns an iterator over all scopes IDs, starting from the current [`Scope`]. + pub fn current_scope_ids(&self) -> impl Iterator + '_ { + self.scopes.ancestor_ids(self.scope_id) + } + + /// Returns the parent of the given [`Scope`], if any. pub fn parent_scope(&self, scope: &Scope) -> Option<&Scope<'a>> { scope.parent.map(|scope_id| &self.scopes[scope_id]) } - /// Returns the first parent of the given scope that is not a [`ScopeKind::Type`] scope, if any. + /// Returns the first parent of the given [`Scope`] that is not of [`ScopeKind::Type`], if any. pub fn first_non_type_parent_scope(&self, scope: &Scope) -> Option<&Scope<'a>> { let mut current_scope = scope; while let Some(parent) = self.parent_scope(current_scope) { @@ -888,20 +947,36 @@ impl<'a> SemanticModel<'a> { None } - /// Returns a mutable reference to the current top most scope. - pub fn scope_mut(&mut self) -> &mut Scope<'a> { - &mut self.scopes[self.scope_id] + /// Return the [`Stmt`] corresponding to the given [`NodeId`]. + #[inline] + pub fn node(&self, node_id: NodeId) -> &NodeRef<'a> { + &self.nodes[node_id] } - /// Returns an iterator over all scopes, starting from the current scope. - pub fn scopes(&self) -> impl Iterator { - self.scopes.ancestors(self.scope_id) + /// Return the [`Stmt`] corresponding to the given [`NodeId`]. + #[inline] + pub fn statement(&self, node_id: NodeId) -> &'a Stmt { + self.nodes + .ancestor_ids(node_id) + .find_map(|id| self.nodes[id].as_statement()) + .expect("No statement found") + } + + /// Given a [`Stmt`], return its parent, if any. + #[inline] + pub fn parent_statement(&self, node_id: NodeId) -> Option<&'a Stmt> { + self.nodes + .ancestor_ids(node_id) + .filter_map(|id| self.nodes[id].as_statement()) + .nth(1) } - /// Returns an iterator over all parent statements. - pub fn parents(&self) -> impl Iterator + '_ { - let node_id = self.stmt_id.expect("No current statement"); - self.stmts.ancestor_ids(node_id).map(|id| self.stmts[id]) + /// Given a [`NodeId`], return the [`NodeId`] of the parent statement, if any. + pub fn parent_statement_id(&self, node_id: NodeId) -> Option { + self.nodes + .ancestor_ids(node_id) + .filter(|id| self.nodes[*id].is_statement()) + .nth(1) } /// Set the [`Globals`] for the current [`Scope`]. @@ -918,7 +993,7 @@ impl<'a> SemanticModel<'a> { range: *range, references: Vec::new(), scope: self.scope_id, - source: self.stmt_id, + source: self.node_id, context: self.execution_context(), exceptions: self.exceptions(), flags: BindingFlags::empty(), @@ -964,25 +1039,74 @@ impl<'a> SemanticModel<'a> { /// Return `true` if the model is at the top level of the module (i.e., in the module scope, /// and not nested within any statements). pub fn at_top_level(&self) -> bool { - self.scope_id.is_global() - && self - .stmt_id - .map_or(true, |stmt_id| self.stmts.parent_id(stmt_id).is_none()) + self.scope_id.is_global() && self.current_statement_parent_id().is_none() } /// Return `true` if the model is in an async context. pub fn in_async_context(&self) -> bool { - for scope in self.scopes() { - if scope.kind.is_async_function() { - return true; - } - if scope.kind.is_function() { - return false; + for scope in self.current_scopes() { + if let ScopeKind::Function(ast::StmtFunctionDef { is_async, .. }) = scope.kind { + return *is_async; } } false } + /// Return `true` if the model is in a nested union expression (e.g., the inner `Union` in + /// `Union[Union[int, str], float]`). + pub fn in_nested_union(&self) -> bool { + // Ex) `Union[Union[int, str], float]` + if self + .current_expression_grandparent() + .and_then(Expr::as_subscript_expr) + .is_some_and(|parent| self.match_typing_expr(&parent.value, "Union")) + { + return true; + } + + // Ex) `int | Union[str, float]` + if self.current_expression_parent().is_some_and(|parent| { + matches!( + parent, + Expr::BinOp(ast::ExprBinOp { + op: Operator::BitOr, + .. + }) + ) + }) { + return true; + } + + false + } + + /// Returns `true` if `left` and `right` are on different branches of an `if`, `match`, or + /// `try` statement. + /// + /// This implementation assumes that the statements are in the same scope. + pub fn different_branches(&self, left: NodeId, right: NodeId) -> bool { + // Collect the branch path for the left statement. + let left = self + .nodes + .branch_id(left) + .iter() + .flat_map(|branch_id| self.branches.ancestor_ids(*branch_id)) + .collect::>(); + + // Collect the branch path for the right statement. + let right = self + .nodes + .branch_id(right) + .iter() + .flat_map(|branch_id| self.branches.ancestor_ids(*branch_id)) + .collect::>(); + + !left + .iter() + .zip(right.iter()) + .all(|(left, right)| left == right) + } + /// Returns `true` if the given [`BindingId`] is used. pub fn is_used(&self, binding_id: BindingId) -> bool { self.bindings[binding_id].is_used() @@ -1046,26 +1170,29 @@ impl<'a> SemanticModel<'a> { exceptions } - /// Generate a [`Snapshot`] of the current model. + /// Generate a [`Snapshot`] of the current semantic model. pub fn snapshot(&self) -> Snapshot { Snapshot { scope_id: self.scope_id, - stmt_id: self.stmt_id, + node_id: self.node_id, + branch_id: self.branch_id, definition_id: self.definition_id, flags: self.flags, } } - /// Restore the model to the given [`Snapshot`]. + /// Restore the semantic model to the given [`Snapshot`]. pub fn restore(&mut self, snapshot: Snapshot) { let Snapshot { scope_id, - stmt_id, + node_id, + branch_id, definition_id, flags, } = snapshot; self.scope_id = scope_id; - self.stmt_id = stmt_id; + self.node_id = node_id; + self.branch_id = branch_id; self.definition_id = definition_id; self.flags = flags; } @@ -1478,7 +1605,8 @@ impl SemanticModelFlags { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Snapshot { scope_id: ScopeId, - stmt_id: Option, + node_id: Option, + branch_id: Option, definition_id: DefinitionId, flags: SemanticModelFlags, } diff --git a/crates/ruff_python_semantic/src/node.rs b/crates/ruff_python_semantic/src/node.rs deleted file mode 100644 index 5523ab62d1813..0000000000000 --- a/crates/ruff_python_semantic/src/node.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::ops::{Index, IndexMut}; - -use ruff_index::{newtype_index, IndexVec}; -use ruff_python_ast::Stmt; -use rustc_hash::FxHashMap; - -use ruff_python_ast::types::RefEquality; - -/// Id uniquely identifying a statement in a program. -/// -/// Using a `u32` is sufficient because Ruff only supports parsing documents with a size of max `u32::max` -/// and it is impossible to have more statements than characters in the file. We use a `NonZeroU32` to -/// take advantage of memory layout optimizations. -#[newtype_index] -#[derive(Ord, PartialOrd)] -pub struct NodeId; - -/// A [`Node`] represents a statement in a program, along with a pointer to its parent (if any). -#[derive(Debug)] -struct Node<'a> { - /// The statement this node represents. - stmt: &'a Stmt, - /// The ID of the parent of this node, if any. - parent: Option, - /// The depth of this node in the tree. - depth: u32, -} - -/// The nodes of a program indexed by [`NodeId`] -#[derive(Debug, Default)] -pub struct Nodes<'a> { - nodes: IndexVec>, - node_to_id: FxHashMap, NodeId>, -} - -impl<'a> Nodes<'a> { - /// Inserts a new node into the node tree and returns its unique id. - /// - /// Panics if a node with the same pointer already exists. - pub(crate) fn insert(&mut self, stmt: &'a Stmt, parent: Option) -> NodeId { - let next_id = self.nodes.next_index(); - if let Some(existing_id) = self.node_to_id.insert(RefEquality(stmt), next_id) { - panic!("Node already exists with id {existing_id:?}"); - } - self.nodes.push(Node { - stmt, - parent, - depth: parent.map_or(0, |parent| self.nodes[parent].depth + 1), - }) - } - - /// Returns the [`NodeId`] of the given node. - #[inline] - pub fn node_id(&self, node: &'a Stmt) -> Option { - self.node_to_id.get(&RefEquality(node)).copied() - } - - /// Return the [`NodeId`] of the parent node. - #[inline] - pub fn parent_id(&self, node_id: NodeId) -> Option { - self.nodes[node_id].parent - } - - /// Return the parent of the given node. - pub fn parent(&self, node: &'a Stmt) -> Option<&'a Stmt> { - let node_id = self.node_to_id.get(&RefEquality(node))?; - let parent_id = self.nodes[*node_id].parent?; - Some(self[parent_id]) - } - - /// Return the depth of the node. - #[inline] - pub(crate) fn depth(&self, node_id: NodeId) -> u32 { - self.nodes[node_id].depth - } - - /// Returns an iterator over all [`NodeId`] ancestors, starting from the given [`NodeId`]. - pub(crate) fn ancestor_ids(&self, node_id: NodeId) -> impl Iterator + '_ { - std::iter::successors(Some(node_id), |&node_id| self.nodes[node_id].parent) - } -} - -impl<'a> Index for Nodes<'a> { - type Output = &'a Stmt; - - #[inline] - fn index(&self, index: NodeId) -> &Self::Output { - &self.nodes[index].stmt - } -} - -impl<'a> IndexMut for Nodes<'a> { - #[inline] - fn index_mut(&mut self, index: NodeId) -> &mut Self::Output { - &mut self.nodes[index].stmt - } -} diff --git a/crates/ruff_python_semantic/src/nodes.rs b/crates/ruff_python_semantic/src/nodes.rs new file mode 100644 index 0000000000000..506623c57e843 --- /dev/null +++ b/crates/ruff_python_semantic/src/nodes.rs @@ -0,0 +1,136 @@ +use std::ops::Index; + +use ruff_index::{newtype_index, IndexVec}; +use ruff_python_ast::{Expr, Ranged, Stmt}; +use ruff_text_size::TextRange; + +use crate::BranchId; + +/// Id uniquely identifying an AST node in a program. +/// +/// Using a `u32` is sufficient because Ruff only supports parsing documents with a size of max +/// `u32::max` and it is impossible to have more nodes than characters in the file. We use a +/// `NonZeroU32` to take advantage of memory layout optimizations. +#[newtype_index] +#[derive(Ord, PartialOrd)] +pub struct NodeId; + +/// An AST node in a program, along with a pointer to its parent node (if any). +#[derive(Debug)] +struct NodeWithParent<'a> { + /// A pointer to the AST node. + node: NodeRef<'a>, + /// The ID of the parent of this node, if any. + parent: Option, + /// The branch ID of this node, if any. + branch: Option, +} + +/// The nodes of a program indexed by [`NodeId`] +#[derive(Debug, Default)] +pub struct Nodes<'a> { + nodes: IndexVec>, +} + +impl<'a> Nodes<'a> { + /// Inserts a new AST node into the tree and returns its unique ID. + pub(crate) fn insert( + &mut self, + node: NodeRef<'a>, + parent: Option, + branch: Option, + ) -> NodeId { + self.nodes.push(NodeWithParent { + node, + parent, + branch, + }) + } + + /// Return the [`NodeId`] of the parent node. + #[inline] + pub fn parent_id(&self, node_id: NodeId) -> Option { + self.nodes[node_id].parent + } + + /// Return the [`BranchId`] of the branch node. + #[inline] + pub(crate) fn branch_id(&self, node_id: NodeId) -> Option { + self.nodes[node_id].branch + } + + /// Returns an iterator over all [`NodeId`] ancestors, starting from the given [`NodeId`]. + pub(crate) fn ancestor_ids(&self, node_id: NodeId) -> impl Iterator + '_ { + std::iter::successors(Some(node_id), |&node_id| self.nodes[node_id].parent) + } +} + +impl<'a> Index for Nodes<'a> { + type Output = NodeRef<'a>; + + #[inline] + fn index(&self, index: NodeId) -> &Self::Output { + &self.nodes[index].node + } +} + +/// A reference to an AST node. Like [`ruff_python_ast::node::AnyNodeRef`], but wraps the node +/// itself (like [`Stmt`]) rather than the narrowed type (like [`ruff_python_ast::StmtAssign`]). +/// +/// TODO(charlie): Replace with [`ruff_python_ast::node::AnyNodeRef`]. This requires migrating +/// the rest of the codebase to use [`ruff_python_ast::node::AnyNodeRef`] and related abstractions, +/// like [`ruff_python_ast::ExpressionRef`] instead of [`Expr`]. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum NodeRef<'a> { + Stmt(&'a Stmt), + Expr(&'a Expr), +} + +impl<'a> NodeRef<'a> { + /// Returns the [`Stmt`] if this is a statement, or `None` if the reference is to another + /// kind of AST node. + pub fn as_statement(&self) -> Option<&'a Stmt> { + match self { + NodeRef::Stmt(stmt) => Some(stmt), + NodeRef::Expr(_) => None, + } + } + + /// Returns the [`Expr`] if this is a expression, or `None` if the reference is to another + /// kind of AST node. + pub fn as_expression(&self) -> Option<&'a Expr> { + match self { + NodeRef::Stmt(_) => None, + NodeRef::Expr(expr) => Some(expr), + } + } + + pub fn is_statement(&self) -> bool { + self.as_statement().is_some() + } + + pub fn is_expression(&self) -> bool { + self.as_expression().is_some() + } +} + +impl Ranged for NodeRef<'_> { + fn range(&self) -> TextRange { + match self { + NodeRef::Stmt(stmt) => stmt.range(), + NodeRef::Expr(expr) => expr.range(), + } + } +} + +impl<'a> From<&'a Expr> for NodeRef<'a> { + fn from(expr: &'a Expr) -> Self { + NodeRef::Expr(expr) + } +} + +impl<'a> From<&'a Stmt> for NodeRef<'a> { + fn from(stmt: &'a Stmt) -> Self { + NodeRef::Stmt(stmt) + } +} diff --git a/crates/ruff_python_semantic/src/reference.rs b/crates/ruff_python_semantic/src/reference.rs index 6c3201f53884e..80a3fdef8d72c 100644 --- a/crates/ruff_python_semantic/src/reference.rs +++ b/crates/ruff_python_semantic/src/reference.rs @@ -3,6 +3,7 @@ use ruff_text_size::TextRange; use std::ops::Deref; use ruff_index::{newtype_index, IndexSlice, IndexVec}; +use ruff_python_ast::Ranged; use ruff_source_file::Locator; use crate::context::ExecutionContext; @@ -26,11 +27,6 @@ impl ResolvedReference { self.scope_id } - /// The range of the reference in the source code. - pub const fn range(&self) -> TextRange { - self.range - } - /// The [`ExecutionContext`] of the reference. pub const fn context(&self) -> ExecutionContext { if self.flags.intersects(SemanticModelFlags::TYPING_CONTEXT) { @@ -41,6 +37,13 @@ impl ResolvedReference { } } +impl Ranged for ResolvedReference { + /// The range of the reference in the source code. + fn range(&self) -> TextRange { + self.range + } +} + /// Id uniquely identifying a read reference in a program. #[newtype_index] pub struct ResolvedReferenceId; diff --git a/crates/ruff_python_semantic/src/scope.rs b/crates/ruff_python_semantic/src/scope.rs index b80d61278467c..3de3b058f9192 100644 --- a/crates/ruff_python_semantic/src/scope.rs +++ b/crates/ruff_python_semantic/src/scope.rs @@ -178,19 +178,12 @@ bitflags! { pub enum ScopeKind<'a> { Class(&'a ast::StmtClassDef), Function(&'a ast::StmtFunctionDef), - AsyncFunction(&'a ast::StmtAsyncFunctionDef), Generator, Module, Type, Lambda(&'a ast::ExprLambda), } -impl ScopeKind<'_> { - pub const fn is_any_function(&self) -> bool { - matches!(self, ScopeKind::Function(_) | ScopeKind::AsyncFunction(_)) - } -} - /// Id uniquely identifying a scope in a program. /// /// Using a `u32` is sufficient because Ruff only supports parsing documents with a size of max `u32::max` diff --git a/crates/ruff_python_stdlib/src/identifiers.rs b/crates/ruff_python_stdlib/src/identifiers.rs index 169959bee2d18..18c0f9a4e626c 100644 --- a/crates/ruff_python_stdlib/src/identifiers.rs +++ b/crates/ruff_python_stdlib/src/identifiers.rs @@ -5,10 +5,7 @@ use crate::keyword::is_keyword; pub fn is_identifier(name: &str) -> bool { // Is the first character a letter or underscore? let mut chars = name.chars(); - if !chars - .next() - .map_or(false, |c| c.is_alphabetic() || c == '_') - { + if !chars.next().is_some_and(|c| c.is_alphabetic() || c == '_') { return false; } @@ -41,7 +38,7 @@ pub fn is_module_name(name: &str) -> bool { let mut chars = name.chars(); if !chars .next() - .map_or(false, |c| c.is_ascii_lowercase() || c == '_') + .is_some_and(|c| c.is_ascii_lowercase() || c == '_') { return false; } diff --git a/crates/ruff_python_stdlib/src/path.rs b/crates/ruff_python_stdlib/src/path.rs index cad9219687336..084923e86c115 100644 --- a/crates/ruff_python_stdlib/src/path.rs +++ b/crates/ruff_python_stdlib/src/path.rs @@ -3,23 +3,23 @@ use std::path::Path; /// Return `true` if the [`Path`] appears to be that of a Python file. pub fn is_python_file(path: &Path) -> bool { path.extension() - .map_or(false, |ext| ext == "py" || ext == "pyi") + .is_some_and(|ext| ext == "py" || ext == "pyi") } /// Return `true` if the [`Path`] is named `pyproject.toml`. pub fn is_project_toml(path: &Path) -> bool { path.file_name() - .map_or(false, |name| name == "pyproject.toml") + .is_some_and(|name| name == "pyproject.toml") } /// Return `true` if the [`Path`] appears to be that of a Python interface definition file (`.pyi`). pub fn is_python_stub_file(path: &Path) -> bool { - path.extension().map_or(false, |ext| ext == "pyi") + path.extension().is_some_and(|ext| ext == "pyi") } /// Return `true` if the [`Path`] appears to be that of a Jupyter notebook (`.ipynb`). pub fn is_jupyter_notebook(path: &Path) -> bool { - path.extension().map_or(false, |ext| ext == "ipynb") + path.extension().is_some_and(|ext| ext == "ipynb") } #[cfg(test)] diff --git a/crates/ruff_python_trivia/Cargo.toml b/crates/ruff_python_trivia/Cargo.toml index a9c5d4a44e3c8..f0f9861e5ade3 100644 --- a/crates/ruff_python_trivia/Cargo.toml +++ b/crates/ruff_python_trivia/Cargo.toml @@ -24,4 +24,3 @@ unic-ucd-ident = "0.9.0" insta = { workspace = true } ruff_python_ast = { path = "../ruff_python_ast" } ruff_python_parser = { path = "../ruff_python_parser" } - diff --git a/crates/ruff_python_trivia/src/cursor.rs b/crates/ruff_python_trivia/src/cursor.rs index 43a750cb4fc6c..336720269cf7f 100644 --- a/crates/ruff_python_trivia/src/cursor.rs +++ b/crates/ruff_python_trivia/src/cursor.rs @@ -30,6 +30,14 @@ impl<'a> Cursor<'a> { self.chars.clone().next().unwrap_or(EOF_CHAR) } + /// Peeks the second character from the input stream without consuming it. + /// Returns [`EOF_CHAR`] if the position is past the end of the file. + pub fn second(&self) -> char { + let mut chars = self.chars.clone(); + chars.next(); + chars.next().unwrap_or(EOF_CHAR) + } + /// Peeks the next character from the input stream without consuming it. /// Returns [`EOF_CHAR`] if the file is at the end of the file. pub fn last(&self) -> char { diff --git a/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_eq.snap b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_eq.snap new file mode 100644 index 0000000000000..26f9c5ae2ce1a --- /dev/null +++ b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_eq.snap @@ -0,0 +1,14 @@ +--- +source: crates/ruff_python_trivia/src/tokenizer.rs +expression: test_case.tokens() +--- +[ + SimpleToken { + kind: EqEqual, + range: 0..2, + }, + SimpleToken { + kind: Equals, + range: 2..3, + }, +] diff --git a/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_invalid_operators.snap b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_invalid_operators.snap new file mode 100644 index 0000000000000..cee59e0ba3d81 --- /dev/null +++ b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_invalid_operators.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff_python_trivia/src/tokenizer.rs +expression: test_case.tokens() +--- +[ + SimpleToken { + kind: RArrow, + range: 0..2, + }, + SimpleToken { + kind: Whitespace, + range: 2..3, + }, + SimpleToken { + kind: Other, + range: 3..4, + }, + SimpleToken { + kind: Bogus, + range: 4..5, + }, +] diff --git a/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_not_eq.snap b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_not_eq.snap new file mode 100644 index 0000000000000..00a7d9c1fcf25 --- /dev/null +++ b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_not_eq.snap @@ -0,0 +1,14 @@ +--- +source: crates/ruff_python_trivia/src/tokenizer.rs +expression: test_case.tokens() +--- +[ + SimpleToken { + kind: NotEqual, + range: 0..2, + }, + SimpleToken { + kind: Equals, + range: 2..3, + }, +] diff --git a/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_operators.snap b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_operators.snap new file mode 100644 index 0000000000000..f0f92f80c0d55 --- /dev/null +++ b/crates/ruff_python_trivia/src/snapshots/ruff_python_trivia__tokenizer__tests__tokenize_operators.snap @@ -0,0 +1,106 @@ +--- +source: crates/ruff_python_trivia/src/tokenizer.rs +expression: test_case.tokens() +--- +[ + SimpleToken { + kind: RArrow, + range: 0..2, + }, + SimpleToken { + kind: Whitespace, + range: 2..3, + }, + SimpleToken { + kind: StarEqual, + range: 3..5, + }, + SimpleToken { + kind: Whitespace, + range: 5..6, + }, + SimpleToken { + kind: LParen, + range: 6..7, + }, + SimpleToken { + kind: Whitespace, + range: 7..8, + }, + SimpleToken { + kind: MinusEqual, + range: 8..10, + }, + SimpleToken { + kind: Whitespace, + range: 10..11, + }, + SimpleToken { + kind: RParen, + range: 11..12, + }, + SimpleToken { + kind: Whitespace, + range: 12..13, + }, + SimpleToken { + kind: Tilde, + range: 13..14, + }, + SimpleToken { + kind: Whitespace, + range: 14..15, + }, + SimpleToken { + kind: DoubleSlash, + range: 15..17, + }, + SimpleToken { + kind: Whitespace, + range: 17..18, + }, + SimpleToken { + kind: DoubleStar, + range: 18..20, + }, + SimpleToken { + kind: Whitespace, + range: 20..21, + }, + SimpleToken { + kind: DoubleStarEqual, + range: 21..24, + }, + SimpleToken { + kind: Whitespace, + range: 24..25, + }, + SimpleToken { + kind: Circumflex, + range: 25..26, + }, + SimpleToken { + kind: Whitespace, + range: 26..27, + }, + SimpleToken { + kind: CircumflexEqual, + range: 27..29, + }, + SimpleToken { + kind: Whitespace, + range: 29..30, + }, + SimpleToken { + kind: Vbar, + range: 30..31, + }, + SimpleToken { + kind: Whitespace, + range: 31..32, + }, + SimpleToken { + kind: VbarEqual, + range: 32..34, + }, +] diff --git a/crates/ruff_python_trivia/src/tokenizer.rs b/crates/ruff_python_trivia/src/tokenizer.rs index 896bc445593a7..d0632abe4c10e 100644 --- a/crates/ruff_python_trivia/src/tokenizer.rs +++ b/crates/ruff_python_trivia/src/tokenizer.rs @@ -1,7 +1,8 @@ use memchr::{memchr2, memchr3, memrchr3_iter}; -use ruff_text_size::{TextLen, TextRange, TextSize}; use unic_ucd_ident::{is_xid_continue, is_xid_start}; +use ruff_text_size::{TextLen, TextRange, TextSize}; + use crate::{is_python_whitespace, Cursor}; /// Searches for the first non-trivia character in `range`. @@ -18,6 +19,24 @@ pub fn first_non_trivia_token(offset: TextSize, code: &str) -> Option SimpleToken { + let mut tokens = SimpleTokenizer::new(code, range) + .skip_trivia() + .skip_while(|token| token.kind == SimpleTokenKind::RParen); + let token = tokens.next().expect("Expected a token"); + debug_assert_eq!(token.kind(), token_kind); + let mut tokens = tokens.skip_while(|token| token.kind == SimpleTokenKind::LParen); + debug_assert_eq!(tokens.next(), None); + token +} + /// Returns the number of newlines between `offset` and the first non whitespace character in the source code. pub fn lines_before(offset: TextSize, code: &str) -> u32 { let mut cursor = Cursor::new(&code[TextRange::up_to(offset)]); @@ -70,28 +89,26 @@ pub fn lines_after(offset: TextSize, code: &str) -> u32 { newlines } -/// Returns the position after skipping any trailing trivia up to, but not including the newline character. -pub fn skip_trailing_trivia(offset: TextSize, code: &str) -> TextSize { - let tokenizer = SimpleTokenizer::starts_at(offset, code); - - for token in tokenizer { - match token.kind() { - SimpleTokenKind::Whitespace - | SimpleTokenKind::Comment - | SimpleTokenKind::Continuation => { - // No op - } - _ => { - return token.start(); - } - } - } - - offset +/// Counts the empty lines after `offset`, ignoring any trailing trivia on the same line as +/// `offset`. +#[allow(clippy::cast_possible_truncation)] +pub fn lines_after_ignoring_trivia(offset: TextSize, code: &str) -> u32 { + // SAFETY: We don't support files greater than 4GB, so casting to u32 is safe. + SimpleTokenizer::starts_at(offset, code) + .skip_while(|token| token.kind != SimpleTokenKind::Newline && token.kind.is_trivia()) + .take_while(|token| { + token.kind == SimpleTokenKind::Newline || token.kind == SimpleTokenKind::Whitespace + }) + .filter(|token| token.kind == SimpleTokenKind::Newline) + .count() as u32 } fn is_identifier_start(c: char) -> bool { - c.is_ascii_alphabetic() || c == '_' || is_non_ascii_identifier_start(c) + if c.is_ascii() { + c.is_ascii_alphabetic() || c == '_' + } else { + is_xid_start(c) + } } // Checks if the character c is a valid continuation character as described @@ -104,10 +121,6 @@ fn is_identifier_continuation(c: char) -> bool { } } -fn is_non_ascii_identifier_start(c: char) -> bool { - is_xid_start(c) -} - #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct SimpleToken { pub kind: SimpleTokenKind, @@ -174,6 +187,9 @@ pub enum SimpleTokenKind { /// `:` Colon, + /// `;` + Semi, + /// '/' Slash, @@ -183,29 +199,215 @@ pub enum SimpleTokenKind { /// `.`. Dot, + /// `+` + Plus, + + /// `-` + Minus, + + /// `=` + Equals, + + /// `>` + Greater, + + /// `<` + Less, + + /// `%` + Percent, + + /// `&` + Ampersand, + + /// `^` + Circumflex, + + /// `|` + Vbar, + + /// `@` + At, + + /// `~` + Tilde, + + /// `==` + EqEqual, + + /// `!=` + NotEqual, + + /// `<=` + LessEqual, + + /// `>=` + GreaterEqual, + + /// `<<` + LeftShift, + + /// `>>` + RightShift, + + /// `**` + DoubleStar, + + /// `**=` + DoubleStarEqual, + + /// `+=` + PlusEqual, + + /// `-=` + MinusEqual, + + /// `*=` + StarEqual, + + /// `/=` + SlashEqual, + + /// `%=` + PercentEqual, + + /// `&=` + AmperEqual, + + /// `|=` + VbarEqual, + + /// `^=` + CircumflexEqual, + + /// `<<=` + LeftShiftEqual, + + /// `>>=` + RightShiftEqual, + + /// `//` + DoubleSlash, + + /// `//=` + DoubleSlashEqual, + + /// `:=` + ColonEqual, + + /// `...` + Ellipsis, + + /// `@=` + AtEqual, + + /// `->` + RArrow, + + /// `and` + And, + + /// `as` + As, + + /// `assert` + Assert, + + /// `async` + Async, + + /// `await` + Await, + + /// `break` + Break, + + /// `class` + Class, + + /// `continue` + Continue, + + /// `def` + Def, + + /// `del` + Del, + + /// `elif` + Elif, + /// `else` Else, + /// `except` + Except, + + /// `finally` + Finally, + + /// `for` + For, + + /// `from` + From, + + /// `global` + Global, + /// `if` If, - /// `elif` - Elif, + /// `import` + Import, /// `in` In, - /// `as` - As, + /// `is` + Is, + + /// `lambda` + Lambda, + + /// `nonlocal` + Nonlocal, + + /// `not` + Not, + + /// `or` + Or, + + /// `pass` + Pass, + + /// `raise` + Raise, + + /// `return` + Return, + + /// `try` + Try, + + /// `while` + While, /// `match` Match, + /// `type` + Type, + + /// `case` + Case, + /// `with` With, - /// `async` - Async, + /// `yield` + Yield, /// Any other non trivia token. Other, @@ -215,23 +417,6 @@ pub enum SimpleTokenKind { } impl SimpleTokenKind { - const fn from_non_trivia_char(c: char) -> SimpleTokenKind { - match c { - '(' => SimpleTokenKind::LParen, - ')' => SimpleTokenKind::RParen, - '[' => SimpleTokenKind::LBracket, - ']' => SimpleTokenKind::RBracket, - '{' => SimpleTokenKind::LBrace, - '}' => SimpleTokenKind::RBrace, - ',' => SimpleTokenKind::Comma, - ':' => SimpleTokenKind::Colon, - '/' => SimpleTokenKind::Slash, - '*' => SimpleTokenKind::Star, - '.' => SimpleTokenKind::Dot, - _ => SimpleTokenKind::Other, - } - } - const fn is_trivia(self) -> bool { matches!( self, @@ -295,15 +480,41 @@ impl<'a> SimpleTokenizer<'a> { fn to_keyword_or_other(&self, range: TextRange) -> SimpleTokenKind { let source = &self.source[range]; match source { + "and" => SimpleTokenKind::And, "as" => SimpleTokenKind::As, + "assert" => SimpleTokenKind::Assert, "async" => SimpleTokenKind::Async, - "else" => SimpleTokenKind::Else, + "await" => SimpleTokenKind::Await, + "break" => SimpleTokenKind::Break, + "class" => SimpleTokenKind::Class, + "continue" => SimpleTokenKind::Continue, + "def" => SimpleTokenKind::Def, + "del" => SimpleTokenKind::Del, "elif" => SimpleTokenKind::Elif, + "else" => SimpleTokenKind::Else, + "except" => SimpleTokenKind::Except, + "finally" => SimpleTokenKind::Finally, + "for" => SimpleTokenKind::For, + "from" => SimpleTokenKind::From, + "global" => SimpleTokenKind::Global, "if" => SimpleTokenKind::If, + "import" => SimpleTokenKind::Import, "in" => SimpleTokenKind::In, + "is" => SimpleTokenKind::Is, + "lambda" => SimpleTokenKind::Lambda, + "nonlocal" => SimpleTokenKind::Nonlocal, + "not" => SimpleTokenKind::Not, + "or" => SimpleTokenKind::Or, + "pass" => SimpleTokenKind::Pass, + "raise" => SimpleTokenKind::Raise, + "return" => SimpleTokenKind::Return, + "try" => SimpleTokenKind::Try, + "while" => SimpleTokenKind::While, "match" => SimpleTokenKind::Match, // Match is a soft keyword that depends on the context but we can always lex it as a keyword and leave it to the caller (parser) to decide if it should be handled as an identifier or keyword. + "type" => SimpleTokenKind::Type, // Type is a soft keyword that depends on the context but we can always lex it as a keyword and leave it to the caller (parser) to decide if it should be handled as an identifier or keyword. + "case" => SimpleTokenKind::Case, "with" => SimpleTokenKind::With, - // ..., + "yield" => SimpleTokenKind::Yield, _ => SimpleTokenKind::Other, // Potentially an identifier, but only if it isn't a string prefix. We can ignore this for now https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals } } @@ -329,6 +540,20 @@ impl<'a> SimpleTokenizer<'a> { } let kind = match first { + // Keywords and identifiers + c if is_identifier_start(c) => { + self.cursor.eat_while(is_identifier_continuation); + let token_len = self.cursor.token_len(); + + let range = TextRange::at(self.offset, token_len); + let kind = self.to_keyword_or_other(range); + + if kind == SimpleTokenKind::Other { + self.bogus = true; + } + kind + } + ' ' | '\t' => { self.cursor.eat_while(|c| matches!(c, ' ' | '\t')); SimpleTokenKind::Whitespace @@ -348,21 +573,156 @@ impl<'a> SimpleTokenizer<'a> { '\\' => SimpleTokenKind::Continuation, - c => { - let kind = if is_identifier_start(c) { - self.cursor.eat_while(is_identifier_continuation); - let token_len = self.cursor.token_len(); - - let range = TextRange::at(self.offset, token_len); - self.to_keyword_or_other(range) + // Non-trivia, non-keyword tokens + '=' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::EqEqual + } else { + SimpleTokenKind::Equals + } + } + '+' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::PlusEqual + } else { + SimpleTokenKind::Plus + } + } + '*' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::StarEqual + } else if self.cursor.eat_char('*') { + if self.cursor.eat_char('=') { + SimpleTokenKind::DoubleStarEqual + } else { + SimpleTokenKind::DoubleStar + } + } else { + SimpleTokenKind::Star + } + } + '/' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::SlashEqual + } else if self.cursor.eat_char('/') { + if self.cursor.eat_char('=') { + SimpleTokenKind::DoubleSlashEqual + } else { + SimpleTokenKind::DoubleSlash + } + } else { + SimpleTokenKind::Slash + } + } + '%' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::PercentEqual + } else { + SimpleTokenKind::Percent + } + } + '|' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::VbarEqual + } else { + SimpleTokenKind::Vbar + } + } + '^' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::CircumflexEqual + } else { + SimpleTokenKind::Circumflex + } + } + '&' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::AmperEqual + } else { + SimpleTokenKind::Ampersand + } + } + '-' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::MinusEqual + } else if self.cursor.eat_char('>') { + SimpleTokenKind::RArrow + } else { + SimpleTokenKind::Minus + } + } + '@' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::AtEqual + } else { + SimpleTokenKind::At + } + } + '!' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::NotEqual } else { - SimpleTokenKind::from_non_trivia_char(c) - }; - - if kind == SimpleTokenKind::Other { self.bogus = true; + SimpleTokenKind::Other } - kind + } + '~' => SimpleTokenKind::Tilde, + ':' => { + if self.cursor.eat_char('=') { + SimpleTokenKind::ColonEqual + } else { + SimpleTokenKind::Colon + } + } + ';' => SimpleTokenKind::Semi, + '<' => { + if self.cursor.eat_char('<') { + if self.cursor.eat_char('=') { + SimpleTokenKind::LeftShiftEqual + } else { + SimpleTokenKind::LeftShift + } + } else if self.cursor.eat_char('=') { + SimpleTokenKind::LessEqual + } else { + SimpleTokenKind::Less + } + } + '>' => { + if self.cursor.eat_char('>') { + if self.cursor.eat_char('=') { + SimpleTokenKind::RightShiftEqual + } else { + SimpleTokenKind::RightShift + } + } else if self.cursor.eat_char('=') { + SimpleTokenKind::GreaterEqual + } else { + SimpleTokenKind::Greater + } + } + ',' => SimpleTokenKind::Comma, + '.' => { + if self.cursor.first() == '.' && self.cursor.second() == '.' { + self.cursor.bump(); + self.cursor.bump(); + SimpleTokenKind::Ellipsis + } else { + SimpleTokenKind::Dot + } + } + + // Bracket tokens + '(' => SimpleTokenKind::LParen, + ')' => SimpleTokenKind::RParen, + '[' => SimpleTokenKind::LBracket, + ']' => SimpleTokenKind::RBracket, + '{' => SimpleTokenKind::LBrace, + '}' => SimpleTokenKind::RBrace, + + _ => { + self.bogus = true; + SimpleTokenKind::Other } }; @@ -463,38 +823,108 @@ impl<'a> SimpleTokenizer<'a> { } SimpleTokenKind::Comment - } else if c == '\\' { - SimpleTokenKind::Continuation } else { - let kind = if is_identifier_continuation(c) { - // if we only have identifier continuations but no start (e.g. 555) we - // don't want to consume the chars, so in that case, we want to rewind the - // cursor to here - let savepoint = self.cursor.clone(); - self.cursor.eat_back_while(is_identifier_continuation); - - let token_len = self.cursor.token_len(); - let range = TextRange::at(self.back_offset - token_len, token_len); - - if self.source[range] - .chars() - .next() - .is_some_and(is_identifier_start) - { - self.to_keyword_or_other(range) - } else { - self.cursor = savepoint; - SimpleTokenKind::Other + match c { + // Keywords and identifiers + c if is_identifier_continuation(c) => { + // if we only have identifier continuations but no start (e.g. 555) we + // don't want to consume the chars, so in that case, we want to rewind the + // cursor to here + let savepoint = self.cursor.clone(); + self.cursor.eat_back_while(is_identifier_continuation); + + let token_len = self.cursor.token_len(); + let range = TextRange::at(self.back_offset - token_len, token_len); + + if self.source[range] + .chars() + .next() + .is_some_and(is_identifier_start) + { + self.to_keyword_or_other(range) + } else { + self.cursor = savepoint; + self.bogus = true; + SimpleTokenKind::Other + } } - } else { - SimpleTokenKind::from_non_trivia_char(c) - }; - if kind == SimpleTokenKind::Other { - self.bogus = true; - } + // Non-trivia tokens that are unambiguous when lexing backwards. + // In other words: these are characters that _don't_ appear at the + // end of a multi-character token (like `!=`). + '\\' => SimpleTokenKind::Continuation, + ':' => SimpleTokenKind::Colon, + '~' => SimpleTokenKind::Tilde, + '%' => SimpleTokenKind::Percent, + '|' => SimpleTokenKind::Vbar, + ',' => SimpleTokenKind::Comma, + ';' => SimpleTokenKind::Semi, + '(' => SimpleTokenKind::LParen, + ')' => SimpleTokenKind::RParen, + '[' => SimpleTokenKind::LBracket, + ']' => SimpleTokenKind::RBracket, + '{' => SimpleTokenKind::LBrace, + '}' => SimpleTokenKind::RBrace, + '&' => SimpleTokenKind::Ampersand, + '^' => SimpleTokenKind::Circumflex, + '+' => SimpleTokenKind::Plus, + '-' => SimpleTokenKind::Minus, + + // Non-trivia tokens that _are_ ambiguous when lexing backwards. + // In other words: these are characters that _might_ mark the end + // of a multi-character token (like `!=` or `->` or `//` or `**`). + '=' | '*' | '/' | '@' | '!' | '<' | '>' | '.' => { + // This could be a single-token token, like `+` in `x + y`, or a + // multi-character token, like `+=` in `x += y`. It could also be a sequence + // of multi-character tokens, like `x ==== y`, which is invalid, _but_ it's + // important that we produce the same token stream when lexing backwards as + // we do when lexing forwards. So, identify the range of the sequence, lex + // forwards, and return the last token. + let mut cursor = self.cursor.clone(); + cursor.eat_back_while(|c| { + matches!( + c, + ':' | '~' + | '%' + | '|' + | '&' + | '^' + | '+' + | '-' + | '=' + | '*' + | '/' + | '@' + | '!' + | '<' + | '>' + | '.' + ) + }); + + let token_len = cursor.token_len(); + let range = TextRange::at(self.back_offset - token_len, token_len); + + let forward_lexer = Self::new(self.source, range); + if let Some(token) = forward_lexer.last() { + // If the token spans multiple characters, bump the cursor. Note, + // though, that we already bumped the cursor to past the last character + // in the token at the very start of `next_token_back`. + for _ in self.source[token.range].chars().rev().skip(1) { + self.cursor.bump_back().unwrap(); + } + token.kind() + } else { + self.bogus = true; + SimpleTokenKind::Other + } + } - kind + _ => { + self.bogus = true; + SimpleTokenKind::Other + } + } } } }; @@ -722,6 +1152,7 @@ impl QuoteKind { #[cfg(test)] mod tests { use insta::assert_debug_snapshot; + use ruff_text_size::{TextLen, TextRange, TextSize}; use crate::tokenizer::{lines_after, lines_before, SimpleToken, SimpleTokenizer}; @@ -797,6 +1228,30 @@ mod tests { test_case.assert_reverse_tokenization(); } + #[test] + fn tokenize_eq() { + // Should tokenize as `==`, then `=`, regardless of whether we're lexing forwards or + // backwards. + let source = "==="; + + let test_case = tokenize(source); + + assert_debug_snapshot!(test_case.tokens()); + test_case.assert_reverse_tokenization(); + } + + #[test] + fn tokenize_not_eq() { + // Should tokenize as `!=`, then `=`, regardless of whether we're lexing forwards or + // backwards. + let source = "!=="; + + let test_case = tokenize(source); + + assert_debug_snapshot!(test_case.tokens()); + test_case.assert_reverse_tokenization(); + } + #[test] fn tokenize_continuation() { let source = "( \\\n )"; @@ -807,6 +1262,27 @@ mod tests { test_case.assert_reverse_tokenization(); } + #[test] + fn tokenize_operators() { + let source = "-> *= ( -= ) ~ // ** **= ^ ^= | |="; + + let test_case = tokenize(source); + + assert_debug_snapshot!(test_case.tokens()); + test_case.assert_reverse_tokenization(); + } + + #[test] + fn tokenize_invalid_operators() { + let source = "-> $="; + + let test_case = tokenize(source); + + assert_debug_snapshot!(test_case.tokens()); + + // note: not reversible: [other, bogus, bogus] vs [bogus, bogus, other] + } + #[test] fn tricky_unicode() { let source = "មុ"; @@ -883,8 +1359,8 @@ mod tests { #[test] fn single_quoted_multiline_string_containing_comment() { let test_case = tokenize( - r#"'This string contains a hash looking like a comment\ -# This is not a comment'"#, + r"'This string contains a hash looking like a comment\ +# This is not a comment'", ); assert_debug_snapshot!(test_case.tokenize_reverse()); @@ -934,14 +1410,14 @@ mod tests { #[test] fn string_with_escaped_quote() { - let test_case = tokenize(r#"'a string \' # containing a hash ' # finally a comment"#); + let test_case = tokenize(r"'a string \' # containing a hash ' # finally a comment"); assert_debug_snapshot!(test_case.tokenize_reverse()); } #[test] fn string_with_double_escaped_backslash() { - let test_case = tokenize(r#"'a string \\' # a comment '"#); + let test_case = tokenize(r"'a string \\' # a comment '"); assert_debug_snapshot!(test_case.tokenize_reverse()); } diff --git a/crates/ruff_python_trivia/src/whitespace.rs b/crates/ruff_python_trivia/src/whitespace.rs index cc8f5563b7b41..5209164870582 100644 --- a/crates/ruff_python_trivia/src/whitespace.rs +++ b/crates/ruff_python_trivia/src/whitespace.rs @@ -4,7 +4,7 @@ use ruff_text_size::{TextRange, TextSize}; /// Extract the leading indentation from a line. pub fn indentation_at_offset<'a>(offset: TextSize, locator: &'a Locator) -> Option<&'a str> { let line_start = locator.line_start(offset); - let indentation = &locator.contents()[TextRange::new(line_start, offset)]; + let indentation = locator.slice(TextRange::new(line_start, offset)); if indentation.chars().all(is_python_whitespace) { Some(indentation) @@ -16,14 +16,14 @@ pub fn indentation_at_offset<'a>(offset: TextSize, locator: &'a Locator) -> Opti /// Return `true` if the node starting the given [`TextSize`] has leading content. pub fn has_leading_content(offset: TextSize, locator: &Locator) -> bool { let line_start = locator.line_start(offset); - let leading = &locator.contents()[TextRange::new(line_start, offset)]; + let leading = locator.slice(TextRange::new(line_start, offset)); leading.chars().any(|char| !is_python_whitespace(char)) } /// Return `true` if the node ending at the given [`TextSize`] has trailing content. pub fn has_trailing_content(offset: TextSize, locator: &Locator) -> bool { let line_end = locator.line_end(offset); - let trailing = &locator.contents()[TextRange::new(offset, line_end)]; + let trailing = locator.slice(TextRange::new(offset, line_end)); for char in trailing.chars() { if char == '#' { @@ -83,32 +83,32 @@ impl PythonWhitespace for str { #[cfg(test)] mod tests { use crate::has_trailing_content; - use ruff_python_ast::{Ranged, Suite}; - use ruff_python_parser::{Parse, ParseError}; + use ruff_python_ast::Ranged; + use ruff_python_parser::{parse_suite, ParseError}; use ruff_source_file::Locator; #[test] fn trailing_content() -> Result<(), ParseError> { let contents = "x = 1"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert!(!has_trailing_content(stmt.end(), &locator)); let contents = "x = 1; y = 2"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert!(has_trailing_content(stmt.end(), &locator)); let contents = "x = 1 "; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert!(!has_trailing_content(stmt.end(), &locator)); let contents = "x = 1 # Comment"; - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert!(!has_trailing_content(stmt.end(), &locator)); @@ -118,7 +118,7 @@ x = 1 y = 2 "# .trim(); - let program = Suite::parse(contents, "")?; + let program = parse_suite(contents, "")?; let stmt = program.first().unwrap(); let locator = Locator::new(contents); assert!(!has_trailing_content(stmt.end(), &locator)); diff --git a/crates/ruff_shrinking/src/main.rs b/crates/ruff_shrinking/src/main.rs index 4c62cfa35534f..1847eb9a8fd54 100644 --- a/crates/ruff_shrinking/src/main.rs +++ b/crates/ruff_shrinking/src/main.rs @@ -36,6 +36,7 @@ use regex::Regex; use ruff_python_ast::statement_visitor::{walk_body, walk_stmt, StatementVisitor}; use ruff_python_ast::visitor::{walk_expr, Visitor}; use ruff_python_ast::{Expr, Ranged, Stmt, Suite}; +use ruff_python_parser::Mode; use ruff_text_size::TextRange; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -86,10 +87,8 @@ impl Strategy for StrategyRemoveModuleMember { ) -> Result> { let iter = ast.iter().map(|stmt| { // trim the newlines the range misses - input[..stmt.range().start().to_usize()] - .trim_end() - .to_string() - + input[stmt.range().end().to_usize()..].trim_start() + input[..stmt.start().to_usize()].trim_end().to_string() + + input[stmt.end().to_usize()..].trim_start() }); Ok(Box::new(iter)) } @@ -275,7 +274,7 @@ impl Strategy for StrategyRemoveToken { input: &'a str, _ast: &'a Suite, ) -> Result> { - let token_ranges: Vec<_> = ruff_python_parser::tokenize(input) + let token_ranges: Vec<_> = ruff_python_parser::tokenize(input, Mode::Module) .into_iter() // At this point we know we have valid python code .map(Result::unwrap) @@ -320,9 +319,9 @@ fn minimization_step( pattern: &Regex, last_strategy_and_idx: Option<(&'static dyn Strategy, usize)>, ) -> Result> { - let tokens = ruff_python_parser::tokenize(input); - let ast = - ruff_python_parser::parse_program_tokens(tokens, "input.py").context("not valid python")?; + let tokens = ruff_python_parser::tokenize(input, Mode::Module); + let ast = ruff_python_parser::parse_program_tokens(tokens, "input.py", false) + .context("not valid python")?; // Try the last succeeding strategy first, skipping all that failed last time if let Some((last_strategy, last_idx)) = last_strategy_and_idx { diff --git a/crates/ruff_wasm/src/lib.rs b/crates/ruff_wasm/src/lib.rs index c3f48a9f286bd..602b18f552a21 100644 --- a/crates/ruff_wasm/src/lib.rs +++ b/crates/ruff_wasm/src/lib.rs @@ -20,10 +20,13 @@ use ruff::rules::{ }; use ruff::settings::configuration::Configuration; use ruff::settings::options::Options; +use ruff::settings::types::PythonVersion; use ruff::settings::{defaults, flags, Settings}; +use ruff_python_ast::PySourceType; use ruff_python_codegen::Stylist; use ruff_python_formatter::{format_module, format_node, PyFormatOptions}; use ruff_python_index::{CommentRangesBuilder, Indexer}; +use ruff_python_parser::AsMode; use ruff_source_file::{Locator, SourceLocation}; #[wasm_bindgen(typescript_custom_section)] @@ -132,7 +135,7 @@ impl Workspace { line_length: Some(LineLength::default()), select: Some(defaults::PREFIXES.to_vec()), tab_size: Some(TabSize::default()), - target_version: Some(defaults::TARGET_VERSION), + target_version: Some(PythonVersion::default()), // Ignore a bunch of options that don't make sense in a single-file editor. cache_dir: None, exclude: None, @@ -196,8 +199,10 @@ impl Workspace { } pub fn check(&self, contents: &str) -> Result { + let source_type = PySourceType::default(); + // Tokenize once. - let tokens: Vec = ruff_python_parser::tokenize(contents); + let tokens: Vec = ruff_python_parser::tokenize(contents, source_type.as_mode()); // Map row and column locations to byte slices (lazily). let locator = Locator::new(contents); @@ -227,6 +232,7 @@ impl Workspace { &self.settings, flags::Noqa::Enabled, None, + source_type, ); let source_code = locator.to_source_code(); @@ -262,7 +268,9 @@ impl Workspace { } pub fn format(&self, contents: &str) -> Result { - let printed = format_module(contents, PyFormatOptions::default()).map_err(into_error)?; + // TODO(konstin): Add an options for py/pyi to the UI (1/2) + let options = PyFormatOptions::from_source_type(PySourceType::default()); + let printed = format_module(contents, options).map_err(into_error)?; Ok(printed.into_code()) } @@ -278,13 +286,10 @@ impl Workspace { let comment_ranges = comment_ranges.finish(); let module = parse_tokens(tokens, Mode::Module, ".").map_err(into_error)?; - let formatted = format_node( - &module, - &comment_ranges, - contents, - PyFormatOptions::default(), - ) - .map_err(into_error)?; + // TODO(konstin): Add an options for py/pyi to the UI (2/2) + let options = PyFormatOptions::from_source_type(PySourceType::default()); + let formatted = + format_node(&module, &comment_ranges, contents, options).map_err(into_error)?; Ok(format!("{formatted}")) } diff --git a/docs/configuration.md b/docs/configuration.md index 25b151cf5f7ed..ee7028124184d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -53,8 +53,8 @@ line-length = 88 # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -# Assume Python 3.10. -target-version = "py310" +# Assume Python 3.8 +target-version = "py38" ``` As an example, the following would configure Ruff to: (1) enforce flake8-bugbear rules, in addition @@ -77,6 +77,7 @@ unfixable = ["B"] [tool.ruff.per-file-ignores] "__init__.py" = ["E402"] "path/to/file.py" = ["E402"] +"**/{tests,docs,tools}/*" = ["E402"] ``` Plugin configurations should be expressed as subsections, e.g.: @@ -328,7 +329,7 @@ For example, `ruff check /path/to/excluded/file.py` will always lint `file.py`. ## Jupyter Notebook discovery -Ruff has built-in experimental support for linting [Jupyter Notebooks](https://jupyter.org/). +Ruff has built-in support for linting [Jupyter Notebooks](https://jupyter.org/). To opt in to linting Jupyter Notebook (`.ipynb`) files, add the `*.ipynb` pattern to your [`include`](settings.md#include) setting, like so: diff --git a/docs/faq.md b/docs/faq.md index 5d00f53694eeb..5394e6e184add 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -321,7 +321,7 @@ For a detailed explanation, see the [contributing guide](contributing.md). ## Does Ruff support Jupyter Notebooks? -Ruff has built-in experimental support for linting [Jupyter Notebooks](https://jupyter.org/). +Ruff has built-in support for linting [Jupyter Notebooks](https://jupyter.org/). To opt in to linting Jupyter Notebook (`.ipynb`) files, add the `*.ipynb` pattern to your [`include`](settings.md#include) setting, like so: diff --git a/docs/tutorial.md b/docs/tutorial.md index 244467449f6e0..f23a167e9e090 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -105,7 +105,7 @@ src = ["src"] ### Rule Selection -Ruff supports [over 500 lint rules](rules.md) split across over 40 built-in plugins, but +Ruff supports [over 600 lint rules](rules.md) split across over 40 built-in plugins, but determining the right set of rules will depend on your project's needs: some rules may be too strict, some are framework-specific, and so on. @@ -242,7 +242,7 @@ This tutorial has focused on Ruff's command-line interface, but Ruff can also be ```yaml - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.282 + rev: v0.0.286 hooks: - id: ruff ``` diff --git a/docs/usage.md b/docs/usage.md index 4c2019c44e7c8..17c2e99db76d1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -22,7 +22,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook: ```yaml - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.282 + rev: v0.0.286 hooks: - id: ruff ``` @@ -32,7 +32,7 @@ Or, to enable autofix: ```yaml - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.282 + rev: v0.0.286 hooks: - id: ruff args: [ --fix, --exit-non-zero-on-fix ] @@ -43,7 +43,7 @@ Or, to run the hook on Jupyter Notebooks too: ```yaml - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.282 + rev: v0.0.286 hooks: - id: ruff types_or: [python, pyi, jupyter] diff --git a/fuzz/fuzz_targets/ruff_parse_simple.rs b/fuzz/fuzz_targets/ruff_parse_simple.rs index 3cbdc6249173e..4c23c2652879d 100644 --- a/fuzz/fuzz_targets/ruff_parse_simple.rs +++ b/fuzz/fuzz_targets/ruff_parse_simple.rs @@ -4,9 +4,8 @@ #![no_main] use libfuzzer_sys::{fuzz_target, Corpus}; -use ruff_python_ast::Suite; use ruff_python_codegen::{Generator, Stylist}; -use ruff_python_parser::{lexer, Mode, Parse, ParseError}; +use ruff_python_parser::{lexer, parse_suite, Mode, ParseError}; use ruff_source_file::Locator; fn do_fuzz(case: &[u8]) -> Corpus { @@ -16,7 +15,7 @@ fn do_fuzz(case: &[u8]) -> Corpus { // just round-trip it once to trigger both parse and unparse let locator = Locator::new(code); - let python_ast = match Suite::parse(code, "fuzzed-source.py") { + let python_ast = match parse_suite(code, "fuzzed-source.py") { Ok(stmts) => stmts, Err(ParseError { offset, .. }) => { let offset = offset.to_usize(); diff --git a/playground/README.md b/playground/README.md index 83d302fa8a940..6613d376f867c 100644 --- a/playground/README.md +++ b/playground/README.md @@ -4,11 +4,27 @@ In-browser playground for Ruff. Available [https://play.ruff.rs/](https://play.r ## Getting started -- To build the WASM module, run `npm run build:wasm` - from the `./playground` directory. -- Install TypeScript dependencies with: `npm install`. -- Start the development server with: `npm run dev`. +First, build the WASM module by running `npm run build:wasm` (release build) or +`npm run build:wasm` (debug build) from the `./playground` directory. -## Implementation +Then, install TypeScript dependencies with `npm install`, and run the development server with +`npm run dev`. -Design based on [Tailwind Play](https://play.tailwindcss.com/). Themed with [`ayu`](https://github.com/dempfi/ayu). +To run the datastore, which is based on [Workers KV](https://developers.cloudflare.com/workers/runtime-apis/kv/), +install the [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/), +then run `npx wrangler dev --local` from the `./playground/db` directory. Note that the datastore is +only required to generate shareable URLs for code snippets. The development datastore does not +require Cloudflare authentication or login, but in turn only persists data locally. + +## Architecture + +The playground is implemented as a single-page React application powered by +[Vite](https://vitejs.dev/), with the editor experience itself powered by +[Monaco](https://github.com/microsoft/monaco-editor). + +The playground stores state in `localStorage`, but supports persisting code snippets to +a persistent datastore based on [Workers KV](https://developers.cloudflare.com/workers/runtime-apis/kv/) +and exposed via a [Cloudflare Worker](https://developers.cloudflare.com/workers/learning/how-workers-works/). + +The playground design is originally based on [Tailwind Play](https://play.tailwindcss.com/), with +additional inspiration from the [Rome Tools Playground](https://docs.rome.tools/playground/). diff --git a/playground/api/.dev.vars b/playground/api/.dev.vars new file mode 100644 index 0000000000000..e9d4d6b87481e --- /dev/null +++ b/playground/api/.dev.vars @@ -0,0 +1,2 @@ +# See: https://developers.cloudflare.com/workers/wrangler/configuration/#environmental-variables +DEV=1 diff --git a/playground/api/README.md b/playground/api/README.md new file mode 100644 index 0000000000000..6e3535e33d381 --- /dev/null +++ b/playground/api/README.md @@ -0,0 +1,5 @@ +# api + +Key-value store based on [Workers KV](https://developers.cloudflare.com/workers/runtime-apis/kv/). + +Used to persist code snippets in the playground and generate shareable URLs. diff --git a/playground/api/package-lock.json b/playground/api/package-lock.json new file mode 100644 index 0000000000000..ee9aa442dec2d --- /dev/null +++ b/playground/api/package-lock.json @@ -0,0 +1,2369 @@ +{ + "name": "api", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "api", + "version": "0.0.0", + "dependencies": { + "@miniflare/kv": "^2.14.0", + "@miniflare/storage-memory": "^2.14.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20230801.0", + "miniflare": "^3.20230801.1", + "typescript": "^5.1.6", + "wrangler": "2.0.27" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz", + "integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==", + "dev": true, + "dependencies": { + "mime": "^3.0.0" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230801.0.tgz", + "integrity": "sha512-f/HaLoQzw0qusw+MXxc4mheFCERj64iJ74EK7klms+Ruv4lGYN2PqoUMAQ8Vq5RqXb/B3nfg3+DUmSP7nbc0Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230801.0.tgz", + "integrity": "sha512-VgfBuT43uN+WOQjVfu96lKcmydQtB08AGG3CxtTLDbbJ36kRUq9lLu2lwhu67GS3264xq2cQngeSx+s6pObHKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230801.0.tgz", + "integrity": "sha512-DVlac5QhxhpmPFC9m4Ztg7La6g5R9uB4dg4C6+8cTckUtAfkXEwO7GIAvsfsumIP6XVOGg58qf/bCzqmJVN62g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230801.0.tgz", + "integrity": "sha512-jbF4sK5x9+w4ovaycfXyOtxe6IK2m0c33hxjmsMYDPGCWfWs6ZOacgFjGwnGG0HirYBv1cglJVMFsnCHoWI4mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230801.0.tgz", + "integrity": "sha512-qTn6cyFUmz3zr0Vr+Y3p2UXdUAV6CB76kD28S+yIqW5nzZYSH5islASeMD9d1NdXhdd1kaAs1t2+1OkGxBP8aw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20230801.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230801.0.tgz", + "integrity": "sha512-RzRUR+J/T3h58qbTZHYntYsnZXu3JnrlZIhqP2hhdyfoZAZ/+ko4wX0foAqlYHi+kXWaWtySHBuMcx6ec6TXlQ==", + "dev": true + }, + "node_modules/@esbuild-plugins/node-globals-polyfill": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", + "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==", + "dev": true, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz", + "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, + "node_modules/@miniflare/cache": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.14.0.tgz", + "integrity": "sha512-0mz0OCzTegiX75uMURLJpDo3DaOCSx9M0gv7NMFWDbK/XrvjoENiBZiKu98UBM5fts0qtK19a+MfB4aT0uBCFg==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "http-cache-semantics": "^4.1.0", + "undici": "5.20.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/cache/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/cli-parser": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.14.0.tgz", + "integrity": "sha512-6Wb0jTMqwI7GRGAhz9WOF8AONUsXXPmwu+Qhg+tnRWtQpJ3DYd5dku1N04L9L1R7np/mD8RrycLyCdg3hLZ3aA==", + "dev": true, + "dependencies": { + "@miniflare/shared": "2.14.0", + "kleur": "^4.1.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/core": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.14.0.tgz", + "integrity": "sha512-BjmV/ZDwsKvXnJntYHt3AQgzVKp/5ZzWPpYWoOnUSNxq6nnRCQyvFvjvBZKnhubcmJCLSqegvz0yHejMA90CTA==", + "dev": true, + "dependencies": { + "@iarna/toml": "^2.2.5", + "@miniflare/queues": "2.14.0", + "@miniflare/shared": "2.14.0", + "@miniflare/watcher": "2.14.0", + "busboy": "^1.6.0", + "dotenv": "^10.0.0", + "kleur": "^4.1.4", + "set-cookie-parser": "^2.4.8", + "undici": "5.20.0", + "urlpattern-polyfill": "^4.0.3" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/core/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/d1": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.14.0.tgz", + "integrity": "sha512-9YoeLAkZuWGAu9BMsoctHoMue0xHzJYZigAJWGvWrqSFT1gBaT+RlUefQCHXggi8P7sOJ1+BKlsWAhkB5wfMWQ==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.7" + } + }, + "node_modules/@miniflare/durable-objects": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.14.0.tgz", + "integrity": "sha512-P8eh1P62BPGpj+MCb1i1lj7Tlt/G3BMmnxHp9duyb0Wro/ILVGPQskZl+iq7DHq1w3C+n0+6/E1B44ff+qn0Mw==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "@miniflare/storage-memory": "2.14.0", + "undici": "5.20.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/durable-objects/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/html-rewriter": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.14.0.tgz", + "integrity": "sha512-7CJZk3xZkxK8tGNofnhgWcChZ8YLx6MhAdN2nn6ONSXrK/TevzEKdL8bnVv1OJ6J8Y23OxvfinOhufr33tMS8g==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "html-rewriter-wasm": "^0.4.1", + "undici": "5.20.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/html-rewriter/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/http-server": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.14.0.tgz", + "integrity": "sha512-APaBlvGRAW+W18ph5ruPXX26/iKdByPz1tZH1OjPAKBDAiKFZSGek4QzUmQALBWLx5VMTMrt7QIe7KE4nM4sdw==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "@miniflare/web-sockets": "2.14.0", + "kleur": "^4.1.4", + "selfsigned": "^2.0.0", + "undici": "5.20.0", + "ws": "^8.2.2", + "youch": "^2.2.2" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/http-server/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@miniflare/http-server/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/http-server/node_modules/youch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/youch/-/youch-2.2.2.tgz", + "integrity": "sha512-/FaCeG3GkuJwaMR34GHVg0l8jCbafZLHiFowSjqLlqhC6OMyf2tPJBu8UirF7/NI9X/R5ai4QfEKUCOxMAGxZQ==", + "dev": true, + "dependencies": { + "@types/stack-trace": "0.0.29", + "cookie": "^0.4.1", + "mustache": "^4.2.0", + "stack-trace": "0.0.10" + } + }, + "node_modules/@miniflare/kv": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.14.0.tgz", + "integrity": "sha512-FHAnVjmhV/VHxgjNf2whraz+k7kfMKlfM+5gO8WT6HrOsWxSdx8OueWVScnOuuDkSeUg5Ctrf5SuztTV8Uy1cg==", + "dependencies": { + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/queues": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.14.0.tgz", + "integrity": "sha512-flS4MqlgBKyv6QBqKD0IofjmMDW9wP1prUNQy2wWPih9lA6bFKmml3VdFeDsPnWtE2J67K0vCTf5kj1Q0qdW1w==", + "dev": true, + "dependencies": { + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.7" + } + }, + "node_modules/@miniflare/r2": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.14.0.tgz", + "integrity": "sha512-+WJJP4J0QzY69HPrG6g5OyW23lJ02WHpHZirCxwPSz8CajooqZCJVx+qvUcNmU8MyKASbUZMWnH79LysuBh+jA==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "undici": "5.20.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/r2/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@miniflare/runner-vm": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.14.0.tgz", + "integrity": "sha512-01CmNzv74u0RZgT/vjV/ggDzECXTG88ZJAKhXyhAx0s2DOLIXzsGHn6pUJIsfPCrtj8nfqtTCp1Vf0UMVWSpmw==", + "dev": true, + "dependencies": { + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/scheduler": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.14.0.tgz", + "integrity": "sha512-/D28OeY/HxcOyY0rkPc2qU/wzxCcUv3/F7NRpgDix37sMkYjAAS51ehVIAkPwAdFEMdantcyVuHNQ2kO1xbT+Q==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "cron-schedule": "^3.0.4" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/shared": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.14.0.tgz", + "integrity": "sha512-O0jAEdMkp8BzrdFCfMWZu76h4Cq+tt3/oDtcTFgzum3fRW5vUhIi/5f6bfndu6rkGbSlzxwor8CJWpzityXGug==", + "dependencies": { + "@types/better-sqlite3": "^7.6.0", + "kleur": "^4.1.4", + "npx-import": "^1.1.4", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/sites": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.14.0.tgz", + "integrity": "sha512-qI8MFZpD1NV+g+HQ/qheDVwscKzwG58J+kAVTU/1fgub2lMLsxhE3Mmbi5AIpyIiJ7Q5Sezqga234CEkHkS7dA==", + "dev": true, + "dependencies": { + "@miniflare/kv": "2.14.0", + "@miniflare/shared": "2.14.0", + "@miniflare/storage-file": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/storage-file": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.14.0.tgz", + "integrity": "sha512-Ps0wHhTO+ie33a58efI0p/ppFXSjlbYmykQXfYtMeVLD60CKl+4Lxor0+gD6uYDFbhMWL5/GMDvyr4AM87FA+Q==", + "dev": true, + "dependencies": { + "@miniflare/shared": "2.14.0", + "@miniflare/storage-memory": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/storage-memory": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.14.0.tgz", + "integrity": "sha512-5aFjEiTSNrHJ+iAiGMCA/TVPnNMrnokG5r0vKrwj4knbf8pisgfP04x18zCgOlG7kaIWNmqdO/vtVT5BIioiSQ==", + "dependencies": { + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/watcher": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.14.0.tgz", + "integrity": "sha512-O8Abg2eHpGmcZb8WyUaA6Av1Mqt5bSrorzz4CrWwsvJHBdekZPIX0GihC9vn327d/1pKRs81YTiSAfBoSZpVIw==", + "dev": true, + "dependencies": { + "@miniflare/shared": "2.14.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/web-sockets": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.14.0.tgz", + "integrity": "sha512-lB1CB4rBq0mbCuh55WgIEH4L3c4/i4MNDBfrQL+6r+wGcr/BJUqF8BHpsfAt5yHWUJVtK5mlMeesS/xpg4Ao1w==", + "dev": true, + "dependencies": { + "@miniflare/core": "2.14.0", + "@miniflare/shared": "2.14.0", + "undici": "5.20.0", + "ws": "^8.2.2" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@miniflare/web-sockets/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz", + "integrity": "sha512-dzrRZCYPXIXfSR1/surNbJ/grU3scTaygS0OMzjlGf71i9sc2fGyHPXXiXmEvNIoE0cGwsanEFMVJxPXmco9Eg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.4.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", + "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==" + }, + "node_modules/@types/stack-trace": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", + "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "dependencies": { + "printable-characters": "^1.0.42" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/better-sqlite3": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.5.0.tgz", + "integrity": "sha512-vbPcv/Hx5WYdyNg/NbcfyaBZyv9s/NVbxb7yCeC5Bq1pVocNxeL2tZmSu3Rlm4IEOTjYdGyzWQgyx0OSdORBzw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "dev": true, + "dependencies": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cron-schedule": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz", + "integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/esbuild": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz", + "integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.51", + "esbuild-android-arm64": "0.14.51", + "esbuild-darwin-64": "0.14.51", + "esbuild-darwin-arm64": "0.14.51", + "esbuild-freebsd-64": "0.14.51", + "esbuild-freebsd-arm64": "0.14.51", + "esbuild-linux-32": "0.14.51", + "esbuild-linux-64": "0.14.51", + "esbuild-linux-arm": "0.14.51", + "esbuild-linux-arm64": "0.14.51", + "esbuild-linux-mips64le": "0.14.51", + "esbuild-linux-ppc64le": "0.14.51", + "esbuild-linux-riscv64": "0.14.51", + "esbuild-linux-s390x": "0.14.51", + "esbuild-netbsd-64": "0.14.51", + "esbuild-openbsd-64": "0.14.51", + "esbuild-sunos-64": "0.14.51", + "esbuild-windows-32": "0.14.51", + "esbuild-windows-64": "0.14.51", + "esbuild-windows-arm64": "0.14.51" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz", + "integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz", + "integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz", + "integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz", + "integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz", + "integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz", + "integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz", + "integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz", + "integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz", + "integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz", + "integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz", + "integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz", + "integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz", + "integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz", + "integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz", + "integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz", + "integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz", + "integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz", + "integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz", + "integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.51", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz", + "integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + } + }, + "node_modules/get-source/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/html-rewriter-wasm": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", + "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", + "dev": true + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/miniflare": { + "version": "3.20230801.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230801.1.tgz", + "integrity": "sha512-4vdA2X2Bo2q4hIKN0QJp1dtiGmu4+tlxo14d89aHCWH5N6yl5tQtqJhkLJFxUX8wkNAgSUOHDYeTnhJ51X6tsQ==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "better-sqlite3": "^8.1.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "http-cache-semantics": "^4.1.0", + "kleur": "^4.1.5", + "set-cookie-parser": "^2.6.0", + "source-map-support": "0.5.21", + "stoppable": "^1.1.0", + "undici": "^5.13.0", + "workerd": "1.20230801.0", + "ws": "^8.11.0", + "youch": "^3.2.2", + "zod": "^3.20.6" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/node-abi": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", + "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npx-import": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/npx-import/-/npx-import-1.1.4.tgz", + "integrity": "sha512-3ShymTWOgqGyNlh5lMJAejLuIv3W1K3fbI5Ewc6YErZU3Sp0PqsNs8UIU1O8z5+KVl/Du5ag56Gza9vdorGEoA==", + "dependencies": { + "execa": "^6.1.0", + "parse-package-name": "^1.0.0", + "semver": "^7.3.7", + "validate-npm-package-name": "^4.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-package-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-package-name/-/parse-package-name-1.0.0.tgz", + "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "node_modules/rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "dev": true, + "dependencies": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semiver": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "dev": true, + "dependencies": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.23.0.tgz", + "integrity": "sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-4.0.3.tgz", + "integrity": "sha512-DOE84vZT2fEcl9gqCUTcnAw5ZY5Id55ikUcziSUntuEFL3pRvavg5kwDmTEUJkeCHInTlV/HexFomgYnzO5kdQ==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-name": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", + "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workerd": { + "version": "1.20230801.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230801.0.tgz", + "integrity": "sha512-4PjyPTbDy39JTpvF3VB95DyQeEGJa8qZsxeal/6L3FBULQ+d90N99lTpgONNkZIRRbOz6ZQk5nDC2wr4TmA3wA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20230801.0", + "@cloudflare/workerd-darwin-arm64": "1.20230801.0", + "@cloudflare/workerd-linux-64": "1.20230801.0", + "@cloudflare/workerd-linux-arm64": "1.20230801.0", + "@cloudflare/workerd-windows-64": "1.20230801.0" + } + }, + "node_modules/wrangler": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.0.27.tgz", + "integrity": "sha512-dH0Nv41OiFsHu+mZFMGv1kEO6lOEoxon8kKHToG0YSpGBsObsxurkoyWJDvkAgtnrM00QF8F1Chy15zs0sjJkg==", + "dev": true, + "dependencies": { + "@cloudflare/kv-asset-handler": "^0.2.0", + "@esbuild-plugins/node-globals-polyfill": "^0.1.1", + "@esbuild-plugins/node-modules-polyfill": "^0.1.4", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "esbuild": "0.14.51", + "miniflare": "^2.6.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "selfsigned": "^2.0.1", + "source-map": "^0.7.4", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=16.7.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/wrangler/node_modules/miniflare": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.14.0.tgz", + "integrity": "sha512-xBOUccq1dm5riOfaqoMWCC1uCqT71EW0x4akQQuGYgm+Q44N1ETEmzXSbFVroJgOHe8Hwpqxo2D7OOFwqFevew==", + "dev": true, + "dependencies": { + "@miniflare/cache": "2.14.0", + "@miniflare/cli-parser": "2.14.0", + "@miniflare/core": "2.14.0", + "@miniflare/d1": "2.14.0", + "@miniflare/durable-objects": "2.14.0", + "@miniflare/html-rewriter": "2.14.0", + "@miniflare/http-server": "2.14.0", + "@miniflare/kv": "2.14.0", + "@miniflare/queues": "2.14.0", + "@miniflare/r2": "2.14.0", + "@miniflare/runner-vm": "2.14.0", + "@miniflare/scheduler": "2.14.0", + "@miniflare/shared": "2.14.0", + "@miniflare/sites": "2.14.0", + "@miniflare/storage-file": "2.14.0", + "@miniflare/storage-memory": "2.14.0", + "@miniflare/web-sockets": "2.14.0", + "kleur": "^4.1.4", + "semiver": "^1.1.0", + "source-map-support": "^0.5.20", + "undici": "5.20.0" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "@miniflare/storage-redis": "2.14.0", + "cron-schedule": "^3.0.4", + "ioredis": "^4.27.9" + }, + "peerDependenciesMeta": { + "@miniflare/storage-redis": { + "optional": true + }, + "cron-schedule": { + "optional": true + }, + "ioredis": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/undici": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", + "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/youch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.2.3.tgz", + "integrity": "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/playground/api/package.json b/playground/api/package.json new file mode 100644 index 0000000000000..278cebe54f680 --- /dev/null +++ b/playground/api/package.json @@ -0,0 +1,20 @@ +{ + "name": "api", + "version": "0.0.0", + "devDependencies": { + "@cloudflare/workers-types": "^4.20230801.0", + "miniflare": "^3.20230801.1", + "typescript": "^5.1.6", + "wrangler": "2.0.27" + }, + "private": true, + "scripts": { + "start": "wrangler dev", + "deploy": "wrangler publish" + }, + "dependencies": { + "@miniflare/kv": "^2.14.0", + "@miniflare/storage-memory": "^2.14.0", + "uuid": "^9.0.0" + } +} diff --git a/playground/api/src/index.ts b/playground/api/src/index.ts new file mode 100644 index 0000000000000..2fbd4eaebfe7d --- /dev/null +++ b/playground/api/src/index.ts @@ -0,0 +1,91 @@ +/** + * A Workers KV-based database for storing shareable code snippets in the Playground. + */ + +export interface Env { + // The Workers KV namespace to use for storing code snippets. + PLAYGROUND: KVNamespace; + // Whether or not we're in a development environment. + DEV?: boolean; +} + +// See: https://developers.cloudflare.com/workers/examples/security-headers/ +const DEFAULT_HEADERS = { + "Permissions-Policy": "interest-cohort=()", + "X-XSS-Protection": "0", + "X-Frame-Options": "DENY", + "X-Content-Type-Options": "nosniff", + "Referrer-Policy": "strict-origin-when-cross-origin", + "Cross-Origin-Embedder-Policy": 'require-corp; report-to="default";', + "Cross-Origin-Opener-Policy": 'same-site; report-to="default";', + "Cross-Origin-Resource-Policy": "same-site", +}; + +const DEVELOPMENT_HEADERS = { + ...DEFAULT_HEADERS, + "Access-Control-Allow-Origin": "*", +}; + +const PRODUCTION_HEADERS = { + ...DEFAULT_HEADERS, + "Access-Control-Allow-Origin": "https://play.ruff.rs", +}; + +export default { + async fetch( + request: Request, + env: Env, + ctx: ExecutionContext, + ): Promise { + const { DEV, PLAYGROUND } = env; + + const headers = DEV ? DEVELOPMENT_HEADERS : PRODUCTION_HEADERS; + + switch (request.method) { + case "GET": { + // Ex) `https://api.astral-1ad.workers.dev/` + // Given an ID, return the corresponding playground. + const { pathname } = new URL(request.url); + const key = pathname.slice(1); + if (!key) { + return new Response("Not Found", { + status: 404, + headers, + }); + } + + const playground = await PLAYGROUND.get(key); + if (playground === null) { + return new Response("Not Found", { + status: 404, + headers, + }); + } + + return new Response(playground, { + status: 200, + headers, + }); + } + + // Ex) `https://api.astral-1ad.workers.dev` + // Given a playground, save it and return its ID. + case "POST": { + const id = crypto.randomUUID(); + const playground = await request.text(); + await PLAYGROUND.put(id, playground); + return new Response(id, { + status: 200, + headers, + }); + } + + default: { + return new Response("Method Not Allowed", { + status: 405, + headers, + }); + } + } + }, +}; diff --git a/playground/api/tsconfig.json b/playground/api/tsconfig.json new file mode 100644 index 0000000000000..39e27fb57f181 --- /dev/null +++ b/playground/api/tsconfig.json @@ -0,0 +1,105 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "es2021" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + "jsx": "react" /* Specify what JSX code is generated. */, + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "es2022" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "@cloudflare/workers-types" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "resolveJsonModule": true /* Enable importing .json files */, + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, + "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true /* Disable emitting files from a compilation. */, + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, + "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, + // "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/playground/api/wrangler.toml b/playground/api/wrangler.toml new file mode 100644 index 0000000000000..0b51a9a2a2b40 --- /dev/null +++ b/playground/api/wrangler.toml @@ -0,0 +1,7 @@ +name = "api" +main = "src/index.ts" +compatibility_date = "2023-08-07" + +kv_namespaces = [ + { binding = "PLAYGROUND", id = "672e16c4fb5e4887845973bf0e9f6021", preview_id = "0a96477e116540e5a6e1eab6d6e7523e" } +] diff --git a/playground/package-lock.json b/playground/package-lock.json index 80222151a8918..bc44767abfa84 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@monaco-editor/react": "^4.4.6", "classnames": "^2.3.2", - "lz-string": "^1.4.4", + "lz-string": "^1.5.0", "monaco-editor": "^0.40.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/playground/package.json b/playground/package.json index 82d08904b644f..78b108f4e9264 100644 --- a/playground/package.json +++ b/playground/package.json @@ -17,7 +17,7 @@ "dependencies": { "@monaco-editor/react": "^4.4.6", "classnames": "^2.3.2", - "lz-string": "^1.4.4", + "lz-string": "^1.5.0", "monaco-editor": "^0.40.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/playground/src/Editor/Editor.tsx b/playground/src/Editor/Editor.tsx index 7b3e12dd9022b..79495084d3a01 100644 --- a/playground/src/Editor/Editor.tsx +++ b/playground/src/Editor/Editor.tsx @@ -5,22 +5,22 @@ import { useMemo, useState, } from "react"; +import { Panel, PanelGroup } from "react-resizable-panels"; import { DEFAULT_PYTHON_SOURCE } from "../constants"; import init, { Diagnostic, Workspace } from "../pkg"; import { ErrorMessage } from "./ErrorMessage"; import Header from "./Header"; -import { useTheme } from "./theme"; -import { persist, persistLocal, restore, stringify } from "./settings"; -import SettingsEditor from "./SettingsEditor"; -import SourceEditor from "./SourceEditor"; -import { Panel, PanelGroup } from "react-resizable-panels"; import PrimarySideBar from "./PrimarySideBar"; -import SecondarySideBar from "./SecondarySideBar"; import { HorizontalResizeHandle } from "./ResizeHandle"; import SecondaryPanel, { SecondaryPanelResult, SecondaryTool, } from "./SecondaryPanel"; +import SecondarySideBar from "./SecondarySideBar"; +import { persist, persistLocal, restore, stringify } from "./settings"; +import SettingsEditor from "./SettingsEditor"; +import SourceEditor from "./SourceEditor"; +import { useTheme } from "./theme"; type Tab = "Source" | "Settings"; @@ -43,11 +43,7 @@ export default function Editor() { error: null, secondary: null, }); - const [source, setSource] = useState({ - pythonSource: "", - settingsSource: "", - revision: 0, - }); + const [source, setSource] = useState(null); const [tab, setTab] = useState("Source"); const [secondaryTool, setSecondaryTool] = useState( @@ -64,9 +60,7 @@ export default function Editor() { ); const [theme, setTheme] = useTheme(); - const initialized = ruffVersion != null; - - // Ideally this would be retrieved right from the URl... but routing without a proper + // Ideally this would be retrieved right from the URL... but routing without a proper // router is hard (there's no location changed event) and pulling in a router // feels overkill. const handleSecondaryToolSelected = (tool: SecondaryTool | null) => { @@ -88,29 +82,32 @@ export default function Editor() { }; useEffect(() => { - init().then(() => { - const [settingsSource, pythonSource] = restore() ?? [ + async function initAsync() { + await init(); + const response = await restore(); + const [settingsSource, pythonSource] = response ?? [ stringify(Workspace.defaultSettings()), DEFAULT_PYTHON_SOURCE, ]; setSource({ - pythonSource, revision: 0, + pythonSource, settingsSource, }); setRuffVersion(Workspace.version()); - }); + } + initAsync().catch(console.error); }, []); const deferredSource = useDeferredValue(source); useEffect(() => { - if (!initialized) { + if (deferredSource == null) { return; } - const { settingsSource, pythonSource } = deferredSource; + const { pythonSource, settingsSource } = deferredSource; try { const config = JSON.parse(settingsSource); @@ -168,46 +165,52 @@ export default function Editor() { secondary: null, }); } - }, [initialized, deferredSource, secondaryTool]); + }, [deferredSource, secondaryTool]); useEffect(() => { - if (initialized) { + if (source != null) { persistLocal(source); } - }, [initialized, source]); + }, [source]); const handleShare = useMemo(() => { - if (!initialized) { + if (source == null) { return undefined; } return () => { - persist(source.settingsSource, source.pythonSource); + return persist(source.settingsSource, source.pythonSource); }; - }, [source, initialized]); + }, [source]); const handlePythonSourceChange = useCallback((pythonSource: string) => { - setSource((state) => ({ - ...state, - pythonSource, - revision: state.revision + 1, - })); + setSource((state) => + state + ? { + ...state, + pythonSource, + revision: state.revision + 1, + } + : null, + ); }, []); const handleSettingsSourceChange = useCallback((settingsSource: string) => { - setSource((state) => ({ - ...state, - settingsSource, - revision: state.revision + 1, - })); + setSource((state) => + state + ? { + ...state, + settingsSource, + revision: state.revision + 1, + } + : null, + ); }, []); - // useMonacoTheme(); - return (

- {initialized ? ( + {source ? ( setTab(tool)} diff --git a/playground/src/Editor/Header.tsx b/playground/src/Editor/Header.tsx index 636e1ae9e593c..537f7d332f2d9 100644 --- a/playground/src/Editor/Header.tsx +++ b/playground/src/Editor/Header.tsx @@ -14,7 +14,7 @@ export default function Header({ onChangeTheme, onShare, }: { - edit: number; + edit: number | null; theme: Theme; version: string | null; onChangeTheme: (theme: Theme) => void; diff --git a/playground/src/Editor/Icons.tsx b/playground/src/Editor/Icons.tsx index 13f4188a5c6a7..0e39f4d8d0ae1 100644 --- a/playground/src/Editor/Icons.tsx +++ b/playground/src/Editor/Icons.tsx @@ -107,3 +107,20 @@ export function TokensIcon() { ); } + +export function FormatterIRIcon() { + return ( + + + + ); +} diff --git a/playground/src/Editor/PrimarySideBar.tsx b/playground/src/Editor/PrimarySideBar.tsx index f4be0292d672c..de4db82b0b532 100644 --- a/playground/src/Editor/PrimarySideBar.tsx +++ b/playground/src/Editor/PrimarySideBar.tsx @@ -16,6 +16,7 @@ export default function PrimarySideBar({ onSelectTool("Source")} selected={selected == "Source"} > @@ -24,6 +25,7 @@ export default function PrimarySideBar({ onSelectTool("Settings")} selected={selected == "Settings"} > diff --git a/playground/src/Editor/SecondarySideBar.tsx b/playground/src/Editor/SecondarySideBar.tsx index 44177c3ea60d4..8cece6e0ceb60 100644 --- a/playground/src/Editor/SecondarySideBar.tsx +++ b/playground/src/Editor/SecondarySideBar.tsx @@ -1,5 +1,10 @@ import SideBar, { SideBarEntry } from "./SideBar"; -import { FormatIcon, StructureIcon, TokensIcon } from "./Icons"; +import { + FormatIcon, + FormatterIRIcon, + StructureIcon, + TokensIcon, +} from "./Icons"; import { SecondaryTool } from "./SecondaryPanel"; interface RightSideBarProps { @@ -15,6 +20,7 @@ export default function SecondarySideBar({ onSelected(SecondaryTool.Format)} > @@ -23,6 +29,7 @@ export default function SecondarySideBar({ onSelected(SecondaryTool.AST)} > @@ -31,6 +38,7 @@ export default function SecondarySideBar({ onSelected(SecondaryTool.Tokens)} > @@ -39,10 +47,11 @@ export default function SecondarySideBar({ onSelected(SecondaryTool.FIR)} > - FIR + ); diff --git a/playground/src/Editor/ShareButton.tsx b/playground/src/Editor/ShareButton.tsx index f7ed4d85ecf16..4938639e50039 100644 --- a/playground/src/Editor/ShareButton.tsx +++ b/playground/src/Editor/ShareButton.tsx @@ -14,7 +14,7 @@ export default function ShareButton({ onShare }: { onShare?: () => void }) { return copied ? ( void }) { > Share - - Copied! - + Copied! ) : ( {children} {selected && ( )} + + {title} ); } + +interface TooltipProps { + children: ReactNode; + position: "left" | "right"; +} + +function Tooltip({ children, position }: TooltipProps) { + return ( + + ); +} diff --git a/playground/src/Editor/ThemeButton.tsx b/playground/src/Editor/ThemeButton.tsx index 72b26edb02a03..a7bed3f584cb1 100644 --- a/playground/src/Editor/ThemeButton.tsx +++ b/playground/src/Editor/ThemeButton.tsx @@ -14,7 +14,7 @@ export default function ThemeButton({ return ( onChange(theme === "light" ? "dark" : "light")} > @@ -28,7 +28,7 @@ export default function ThemeButton({ strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" - className="stroke-black hover:stroke-radiate hover:fill-black fill-radiate" + className="stroke-black hover:stroke-white hover:fill-black fill-radiate" > diff --git a/playground/src/Editor/api.ts b/playground/src/Editor/api.ts new file mode 100644 index 0000000000000..22d3bfc26a43c --- /dev/null +++ b/playground/src/Editor/api.ts @@ -0,0 +1,33 @@ +const API_URL = import.meta.env.PROD + ? "https://api.astral-1ad.workers.dev" + : "http://0.0.0.0:8787"; + +export type Playground = { + pythonSource: string; + settingsSource: string; +}; + +/** + * Fetch a playground by ID. + */ +export async function fetchPlayground(id: string): Promise { + const response = await fetch(`${API_URL}/${encodeURIComponent(id)}`); + if (!response.ok) { + throw new Error(`Failed to fetch playground ${id}: ${response.status}`); + } + return await response.json(); +} + +/** + * Save a playground and return its ID. + */ +export async function savePlayground(playground: Playground): Promise { + const response = await fetch(API_URL, { + method: "POST", + body: JSON.stringify(playground), + }); + if (!response.ok) { + throw new Error(`Failed to save playground: ${response.status}`); + } + return await response.text(); +} diff --git a/playground/src/Editor/settings.ts b/playground/src/Editor/settings.ts index 34e447eee347f..411399da5d92b 100644 --- a/playground/src/Editor/settings.ts +++ b/playground/src/Editor/settings.ts @@ -1,4 +1,5 @@ import lzstring from "lz-string"; +import { fetchPlayground, savePlayground } from "./api"; export type Settings = { [K: string]: any }; @@ -22,29 +23,43 @@ export function stringify(settings: Settings): string { /** * Persist the configuration to a URL. */ -export async function persist(settingsSource: string, pythonSource: string) { - const hash = lzstring.compressToEncodedURIComponent( - settingsSource.replaceAll("$$$", "$$$$$$") + "$$$" + pythonSource, - ); - await navigator.clipboard.writeText( - window.location.href.split("#")[0] + "#" + hash, - ); +export async function persist( + settingsSource: string, + pythonSource: string, +): Promise { + const id = await savePlayground({ settingsSource, pythonSource }); + await navigator.clipboard.writeText(`${window.location.origin}/${id}`); } /** * Restore the configuration from a URL. */ -export function restore(): [string, string] | null { - const value = lzstring.decompressFromEncodedURIComponent( - window.location.hash.slice(1), - ); - - if (value == null) { - return restoreLocal(); - } else { +export async function restore(): Promise<[string, string] | null> { + // Legacy URLs, stored as encoded strings in the hash, like: + // https://play.ruff.rs/#eyJzZXR0aW5nc1NvdXJjZ... + const hash = window.location.hash.slice(1); + if (hash) { + const value = lzstring.decompressFromEncodedURIComponent( + window.location.hash.slice(1), + )!; const [settingsSource, pythonSource] = value.split("$$$"); return [settingsSource.replaceAll("$$$$$$", "$$$"), pythonSource]; } + + // URLs stored in the database, like: + // https://play.ruff.rs/1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed + const id = window.location.pathname.slice(1); + if (id) { + const playground = await fetchPlayground(id); + if (playground == null) { + return null; + } + const { settingsSource, pythonSource } = playground; + return [settingsSource, pythonSource]; + } + + // If no URL is present, restore from local storage. + return restoreLocal(); } function restoreLocal(): [string, string] | null { diff --git a/playground/src/index.css b/playground/src/index.css index 5c9d5245d2378..b644d5add34e7 100644 --- a/playground/src/index.css +++ b/playground/src/index.css @@ -17,8 +17,8 @@ html, } .shadow-copied { - --tw-shadow: 0 0 0 1px theme("colors.radiate"), - inset 0 0 0 1px theme("colors.radiate"); + --tw-shadow: 0 0 0 1px theme("colors.white"), + inset 0 0 0 1px theme("colors.white"); --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), inset 0 0 0 1px var(--tw-shadow-color); diff --git a/pyproject.toml b/pyproject.toml index 304491f39244a..f2d88514430fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "maturin" [project] name = "ruff" -version = "0.0.282" +version = "0.0.286" description = "An extremely fast Python linter, written in Rust." authors = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }] maintainers = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }] diff --git a/ruff.schema.json b/ruff.schema.json index 87ddf7002cc55..beb32b04ede19 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -376,7 +376,7 @@ ] }, "line-length": { - "description": "The line length to use when enforcing long-lines violations (like `E501`).", + "description": "The line length to use when enforcing long-lines violations (like `E501`). Must be greater than `0`.", "anyOf": [ { "$ref": "#/definitions/LineLength" @@ -560,7 +560,7 @@ ] }, "target-version": { - "description": "The minimum Python version to target, e.g., when considering automatic code upgrades, like rewriting type annotations.\n\nIf omitted, and Ruff is configured via a `pyproject.toml` file, the target version will be inferred from its `project.requires-python` field (e.g., `requires-python = \">=3.8\"`). If Ruff is configured via `ruff.toml` or `.ruff.toml`, no such inference will be performed.", + "description": "The minimum Python version to target, e.g., when considering automatic code upgrades, like rewriting type annotations. Ruff will not propose changes using features that are not available in the given version.\n\nFor example, to represent supporting Python >=3.10 or ==3.10 specify `target-version = \"py310\"`.\n\nIf omitted, and Ruff is configured via a `pyproject.toml` file, the target version will be inferred from its `project.requires-python` field (e.g., `requires-python = \">=3.8\"`). If Ruff is configured via `ruff.toml` or `.ruff.toml`, no such inference will be performed.", "anyOf": [ { "$ref": "#/definitions/PythonVersion" @@ -955,7 +955,7 @@ ] }, "raises-extend-require-match-for": { - "description": "List of additional exception names that require a match= parameter in a `pytest.raises()` call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.", + "description": "List of additional exception names that require a match= parameter in a `pytest.raises()` call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.\n\nSupports glob patterns. For more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).", "type": [ "array", "null" @@ -965,7 +965,7 @@ } }, "raises-require-match-for": { - "description": "List of exception names that require a match= parameter in a `pytest.raises()` call.", + "description": "List of exception names that require a match= parameter in a `pytest.raises()` call.\n\nSupports glob patterns. For more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).", "type": [ "array", "null" @@ -1062,6 +1062,16 @@ "additionalProperties": { "$ref": "#/definitions/ApiBan" } + }, + "banned-module-level-imports": { + "description": "List of specific modules that may not be imported at module level, and should instead be imported lazily (e.g., within a function definition, or an `if TYPE_CHECKING:` block, or some other nested context).", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } } }, "additionalProperties": false @@ -1080,7 +1090,7 @@ } }, "runtime-evaluated-base-classes": { - "description": "Exempt classes that list any of the enumerated classes as a base class from needing to be moved into type-checking blocks.", + "description": "Exempt classes that list any of the enumerated classes as a base class from needing to be moved into type-checking blocks.\n\nCommon examples include Pydantic's `pydantic.BaseModel` and SQLAlchemy's `sqlalchemy.orm.DeclarativeBase`, but can also support user-defined classes that inherit from those base classes. For example, if you define a common `DeclarativeBase` subclass that's used throughout your project (e.g., `class Base(DeclarativeBase) ...` in `base.py`), you can add it to this list (`runtime-evaluated-base-classes = [\"base.Base\"]`) to exempt models from being moved into type-checking blocks.", "type": [ "array", "null" @@ -1100,7 +1110,7 @@ } }, "strict": { - "description": "Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module. See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.", + "description": "Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module.\n\nSee flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.", "type": [ "boolean", "null" @@ -1179,6 +1189,13 @@ "type": "string" } }, + "detect-same-package": { + "description": "Whether to automatically mark imports from within the same package as first-party. For example, when `detect-same-package = true`, then when analyzing files within the `foo` package, any imports from within the `foo` package will be considered first-party.\n\nThis heuristic is often unnecessary when `src` is configured to detect all first-party sources; however, if `src` is _not_ configured, this heuristic can be useful to detect first-party imports from _within_ (but not _across_) first-party packages.", + "type": [ + "boolean", + "null" + ] + }, "extra-standard-library": { "description": "A list of modules to consider standard-library, in addition to those known to Ruff in advance.\n\nSupports glob patterns. For more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).", "type": [ @@ -1481,7 +1498,7 @@ ] }, "max-doc-length": { - "description": "The maximum line length to allow for line-length violations within documentation (`W505`), including standalone comments.", + "description": "The maximum line length to allow for line-length violations within documentation (`W505`), including standalone comments. By default, this is set to null which disables reporting violations.\n\nSee the [`doc-line-too-long`](https://beta.ruff.rs/docs/rules/doc-line-too-long/) rule for more information.", "anyOf": [ { "$ref": "#/definitions/LineLength" @@ -2149,6 +2166,7 @@ "PIE800", "PIE804", "PIE807", + "PIE808", "PIE81", "PIE810", "PL", @@ -2203,6 +2221,7 @@ "PLE1206", "PLE13", "PLE130", + "PLE1300", "PLE1307", "PLE131", "PLE1310", @@ -2258,6 +2277,7 @@ "PLR55", "PLR550", "PLR5501", + "PLR6301", "PLW", "PLW0", "PLW01", @@ -2282,12 +2302,15 @@ "PLW150", "PLW1508", "PLW1509", + "PLW151", + "PLW1510", "PLW1641", "PLW2", "PLW29", "PLW290", "PLW2901", "PLW3", + "PLW3201", "PLW33", "PLW330", "PLW3301", @@ -2308,6 +2331,7 @@ "PT011", "PT012", "PT013", + "PT014", "PT015", "PT016", "PT017", @@ -2321,6 +2345,7 @@ "PT024", "PT025", "PT026", + "PT027", "PTH", "PTH1", "PTH10", @@ -2382,6 +2407,7 @@ "PYI016", "PYI017", "PYI018", + "PYI019", "PYI02", "PYI020", "PYI021", @@ -2408,9 +2434,11 @@ "PYI049", "PYI05", "PYI050", + "PYI051", "PYI052", "PYI053", "PYI054", + "PYI055", "PYI056", "Q", "Q0", @@ -2452,6 +2480,7 @@ "RUF013", "RUF015", "RUF016", + "RUF017", "RUF1", "RUF10", "RUF100", @@ -2603,6 +2632,7 @@ "TID25", "TID251", "TID252", + "TID253", "TRY", "TRY0", "TRY00", @@ -2665,6 +2695,8 @@ "UP037", "UP038", "UP039", + "UP04", + "UP040", "W", "W1", "W19", @@ -2735,7 +2767,7 @@ "description": "The size of a tab.", "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 1.0 }, "Version": { "type": "string" diff --git a/rust-toolchain b/rust-toolchain index bfe79d0bddb06..12816e6276f8b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.70 +1.71 diff --git a/scripts/check_docs_formatted.py b/scripts/check_docs_formatted.py index c18d7a86c91b5..2b55a8312747d 100755 --- a/scripts/check_docs_formatted.py +++ b/scripts/check_docs_formatted.py @@ -37,10 +37,13 @@ "indentation-with-invalid-multiple", "line-too-long", "missing-trailing-comma", + "missing-whitespace", + "missing-whitespace-after-keyword", "missing-whitespace-around-arithmetic-operator", "missing-whitespace-around-bitwise-or-shift-operator", "missing-whitespace-around-modulo-operator", "missing-whitespace-around-operator", + "missing-whitespace-around-parameter-equals", "multi-line-implicit-string-concatenation", "multiple-leading-hashes-for-block-comment", "multiple-spaces-after-comma", @@ -66,6 +69,7 @@ "triple-single-quotes", "under-indentation", "unexpected-indentation-comment", + "unexpected-spaces-around-keyword-parameter-equals", "unicode-kind-prefix", "unnecessary-class-parentheses", "useless-semicolon", @@ -82,6 +86,8 @@ "missing-newline-at-end-of-file", "mixed-spaces-and-tabs", "no-indented-block", + "non-pep695-type-alias", # requires Python 3.12 + "syntax-error", "tab-after-comma", "tab-after-keyword", "tab-after-operator", diff --git a/scripts/check_ecosystem.py b/scripts/check_ecosystem.py index ed7c876811c65..607819b263918 100755 --- a/scripts/check_ecosystem.py +++ b/scripts/check_ecosystem.py @@ -106,17 +106,24 @@ async def _get_commit(self: Self, checkout_dir: Path) -> str: REPOSITORIES: list[Repository] = [ + Repository("DisnakeDev", "disnake", "master"), Repository("apache", "airflow", "main", select="ALL"), - Repository("bokeh", "bokeh", "branch-3.2", select="ALL"), + Repository("bokeh", "bokeh", "branch-3.3", select="ALL"), + Repository("commaai", "openpilot", "master"), + Repository("freedomofpress", "securedrop", "develop"), + Repository("ibis-project", "ibis", "master"), + Repository("jrnl-org", "jrnl", "develop"), Repository("pypa", "build", "main"), Repository("pypa", "cibuildwheel", "main"), - Repository("pypa", "setuptools", "main"), Repository("pypa", "pip", "main"), + Repository("pypa", "setuptools", "main"), Repository("python", "mypy", "master"), - Repository("DisnakeDev", "disnake", "master"), + Repository("python", "typeshed", "main", select="PYI"), + Repository("python-poetry", "poetry", "master"), Repository("scikit-build", "scikit-build", "main"), Repository("scikit-build", "scikit-build-core", "main"), - Repository("python", "typeshed", "main", select="PYI"), + Repository("sphinx-doc", "sphinx", "master"), + Repository("tiangolo", "fastapi", "master"), Repository("zulip", "zulip", "main", select="ALL"), ] @@ -299,7 +306,6 @@ def read_projects_jsonl(projects_jsonl: Path) -> dict[tuple[str, str], Repositor r"^(?P
[+-]) (?P(?P[^:]+):(?P\d+):\d+:) (?P.*)$",
 )
 
-
 T = TypeVar("T")
 
 
diff --git a/scripts/ecosystem_all_check.sh b/scripts/ecosystem_all_check.sh
index 7eb593c469185..7c3233cc33b9a 100755
--- a/scripts/ecosystem_all_check.sh
+++ b/scripts/ecosystem_all_check.sh
@@ -6,7 +6,9 @@
 # [kinda dangerous](https://moyix.blogspot.com/2022/09/someones-been-messing-with-my-subnormals.html)
 #
 # Usage:
-# ```
+# ```shell
+# # You can also use any other check_ecosystem.py input file
+# curl https://raw.githubusercontent.com/akx/ruff-usage-aggregate/master/data/known-github-tomls-clean.jsonl > github_search.jsonl
 # cargo build --release --target x86_64-unknown-linux-musl --bin ruff
 # scripts/ecosystem_all_check.sh check --select RUF200
 # ```
diff --git a/scripts/formatter_ecosystem_checks.sh b/scripts/formatter_ecosystem_checks.sh
index b213a27fd9ea2..46966c91cc224 100755
--- a/scripts/formatter_ecosystem_checks.sh
+++ b/scripts/formatter_ecosystem_checks.sh
@@ -17,43 +17,56 @@ dir="$target/progress_projects"
 mkdir -p "$dir"
 
 # small util library
-if [ ! -d "$dir/build" ]; then
-  git clone --filter=tree:0 https://github.com/pypa/build "$dir/build"
-  git -C "$dir/build" checkout d90f9ac6503a40ddbfaef94b7a7040f87178a4b3
+if [ ! -d "$dir/twine/.git" ]; then
+  git clone --filter=tree:0 https://github.com/pypa/twine "$dir/twine"
 fi
+git -C "$dir/twine" checkout 0bb428c410b8df64c04dc881ac1db37d932f3066
+
 # web framework that implements a lot of magic
-if [ ! -d "$dir/django" ]; then
+if [ ! -d "$dir/django/.git" ]; then
   git clone --filter=tree:0 https://github.com/django/django "$dir/django"
-  git -C "$dir/django" checkout 95e4d6b81312fdd9f8ebf3385be1c1331168b5cf
 fi
+git -C "$dir/django" checkout 48a1929ca050f1333927860ff561f6371706968a
+
 # an ML project
-if [ ! -d "$dir/transformers" ]; then
+if [ ! -d "$dir/transformers/.git" ]; then
   git clone --filter=tree:0 https://github.com/huggingface/transformers "$dir/transformers"
-  git -C "$dir/transformers" checkout c9a82be592ca305180a7ab6a36e884bca1d426b8
 fi
+git -C "$dir/transformers" checkout 62396cff46854dc53023236cfeb785993fa70067
+
 # type annotations
-if [ ! -d "$dir/typeshed" ]; then
+if [ ! -d "$dir/typeshed/.git" ]; then
   git clone --filter=tree:0 https://github.com/python/typeshed "$dir/typeshed"
-  git -C "$dir/typeshed" checkout 7d33060e6ae3ebe54462a891f0c566c97371915b
 fi
+git -C "$dir/typeshed" checkout 2c15a8e7906e19f49bb765e2807dd0079fe9c04b
+
 # python 3.11, typing and 100% test coverage
-if [ ! -d "$dir/warehouse" ]; then
+if [ ! -d "$dir/warehouse/.git" ]; then
   git clone --filter=tree:0 https://github.com/pypi/warehouse "$dir/warehouse"
-  git -C "$dir/warehouse" checkout fe6455c0a946e81f61d72edc1049f536d8bba903
 fi
-# django project
-if [ ! -d "$dir/zulip" ]; then
+git -C "$dir/warehouse" checkout 6be6bccf07dace18784ea8aeac7906903fdbcf3a
+
+# zulip, a django user
+if [ ! -d "$dir/zulip/.git" ]; then
   git clone --filter=tree:0 https://github.com/zulip/zulip "$dir/zulip"
-  git -C "$dir/zulip" checkout 6cb080c4479546a7f5cb017fcddea56605910b48
 fi
+git -C "$dir/zulip" checkout 328cdde24331b82baa4c9b1bf1cb7b2015799826
+
+# cpython itself
+if [ ! -d "$dir/cpython/.git" ]; then
+  git clone --filter=tree:0 https://github.com/python/cpython "$dir/cpython"
+fi
+git -C "$dir/cpython" checkout 1a1bfc28912a39b500c578e9f10a8a222638d411
 
 # Uncomment if you want to update the hashes
-# for i in "$dir"/*/; do git -C "$i" switch main && git -C "$i" pull && echo "# $(basename "$i") $(git -C "$i" rev-parse HEAD)"; done
+#for i in "$dir"/*/; do git -C "$i" switch main && git -C "$i" pull; done
+#for i in "$dir"/*/; do echo "# $(basename "$i") $(git -C "$i" rev-parse HEAD)"; done
 
-time cargo run --bin ruff_dev -- format-dev --stability-check --error-file "$target/progress_projects_errors.txt" \
-  --multi-project "$dir" >"$target/progress_projects_report.txt" || (
+time cargo run --bin ruff_dev -- format-dev --stability-check \
+  --error-file "$target/progress_projects_errors.txt" --log-file "$target/progress_projects_log.txt" --stats-file "$target/progress_projects_stats.txt" \
+  --files-with-errors 16 --multi-project "$dir" || (
   echo "Ecosystem check failed"
-  cat "$target/progress_projects_report.txt"
+  cat "$target/progress_projects_log.txt"
   exit 1
 )
-grep "similarity index" "$target/progress_projects_report.txt" | sort
+cat "$target/progress_projects_stats.txt"